EDN Admin
Well-known member
Hi,
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri I have been working on changing old VB6 code over to VB2010. VB6 program receives UDP byte data that is send from real time computer
system then moves the data into a VB6 TYPE (structure) for storage into database and display system. Now Iâm trying to do the same thing in 2010 but I keep getting an System.AccessViolationException error when I try to run a sample code from MSDN an
function called ConvertBytesToStructure. Below is the code I put together. It may be that I donât have the structure created correctly. Please help.
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-family:Calibri; font-size:small
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri Thanks
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri Don
<br/>
Option Strict Off<br/>
Option Explicit On
Imports SocketTools<br/>
Imports SocketTools.SocketWrench<br/>
Imports System.Runtime.InteropServices<br/>
Imports System.Text
Public Class Form1
Inherits System.Windows.Forms.Form
Private WithEvents Socket As New SocketTools.SocketWrench
This the orginal VB6 TYPE Structure<br/>
----------------------------------------------------------------------<br/>
Private Type tcsDataType Real data coming from TM TCS System<br/>
MsgID As Long DINT<br/>
SeqCount As Long {DINT}<br/>
QDIntelSysCntr As Long {DWORD}<br/>
StripID As String * 10 in TCS as StripID(0 To 9) As Byte<br/>
ExitStripID As String * 10 in TCS as StripID(0 To 9) As Byte<br/>
StripWidth As Single<br/>
StripSetThick As Single<br/>
ActStripLength As Single<br/>
ActSpeed As Single<br/>
ActFlatAct(0 To 53) As Single<br/>
End Type
Private fromData As tcsDataType<br/>
Private sendData As tcsDataType<br/>
Private fromBuffer(524) As Byte Was 272<br/>
Private sendBuffer(264) As Byte Was 272<br/>
----------------------------------------------------------------------
<br/>
Private Structure tcsDataStructure<br/>
Dim MsgID As Int32<br/>
Dim SeqCount As Int32<br/>
Dim QDIntelSysCntr As Int32<br/>
Dim StripID() As Byte<br/>
Dim ExitStripID() As Byte<br/>
Dim StripWidth As Single<br/>
Dim StripSetThick As Single<br/>
Dim ActStripLength As Single<br/>
Dim ActSpeed As Single<br/>
Dim ActFlatAct() As Single<br/>
End Structure
Dim ByteClear() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}<br/>
Dim FlatClear() As Single = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0}<br/>
Dim Tst As New tcsDataStructure With {.MsgID = 0,<br/>
.SeqCount
= 0,<br/>
.QDIntelSysCntr
= 0,<br/>
.StripID =
ByteClear,<br/>
.ExitStripID
= ByteClear,<br/>
.StripWidth
= 0.0,<br/>
.StripSetThick
= 0.0,<br/>
.ActStripLength
= 0.0,<br/>
.ActSpeed
= 0.0,<br/>
.ActFlatAct
= FlatClear}
Function to Create structure must be called first<br/>
Private Function BulidStr(ByVal Buff() As Byte, ByVal MyType As System.Type) As Object<br/>
Dim MyGC As GCHandle = GCHandle.Alloc(Buff, GCHandleType.Pinned)<br/>
Marshals data from an unmanaged block of memory to a newly<br/>
allocated managed object of the specified type.<br/>
Dim Obj As Object = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyType)<br/>
Return Obj<br/>
Free GChandle to avoid memory leaks<br/>
MyGC.Free()<br/>
End Function
Private Function ConvertBytesToStructure(ByVal data() As Byte, ByVal struct As System.Type) As tcsDataStructure<br/>
Create an unmanaged handle to the data array
<br/>
Dim gc As GCHandle<br/>
Try<br/>
gc = GCHandle.Alloc(data, GCHandleType.Pinned)<br/>
Marshal the data at the pointer address into the structure specified
<br/>
Dim obj As tcsDataStructure = DirectCast(Marshal.PtrToStructure(gc.AddrOfPinnedObject, struct), tcsDataStructure)<br/>
Return the object created by the PtrToStructure call
<br/>
Return obj<br/>
Finally<br/>
gc.Free()<br/>
End Try
End Function
Private Sub UpdateListBox(ByVal message As String)<br/>
ListBox1.Items.Add(message)<br/>
ListBox1.SelectedIndex = ListBox1.Items.Count - 1<br/>
ListBox1.ClearSelected()<br/>
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click<br/>
Dim strLocalAddress As String<br/>
Dim nLocalPort As Integer
strLocalAddress = TextBox1.Text.Trim()<br/>
If strLocalAddress.Length = 0 Then<br/>
strLocalAddress = "0.0.0.0"<br/>
End If
nLocalPort = Int32.Parse(TextBox2.Text)<br/>
If nLocalPort < 1 Or nLocalPort > 65535 Then<br/>
MsgBox("Please specify a valid local port number", MsgBoxStyle.Exclamation, "Error")<br/>
Exit Sub<br/>
End If
If the Handle property is -1, this means that the UDP socket has not been<br/>
created. Initialize the socket properties and create a datagram socket<br/>
using the Bind method. By setting Blocking to false, the OnRead event will<br/>
be raised when a remote host sends us a datagram.<br/>
If Socket.Handle = -1 Then<br/>
Socket.Protocol = SocketProtocol.socketDatagram<br/>
Socket.Blocking = False
Bind to the specified IP address and port number<br/>
If Not Socket.Bind(strLocalAddress, nLocalPort) Then<br/>
MsgBox(Socket.LastErrorString, MsgBoxStyle.Exclamation, "Error")<br/>
Exit Sub<br/>
End If<br/>
Button1.Text = "Stop"<br/>
UpdateListBox(String.Format("Started listening for datagrams on {0}:{1}", strLocalAddress, nLocalPort))<br/>
Else<br/>
Close the datagram socket using the Disconnect method<br/>
Socket.Disconnect()<br/>
Button1.Text = "Start"<br/>
UpdateListBox("Stopped listening for datagrams")<br/>
End If
End Sub
Private Sub Socket_OnRead(ByVal sender As Object, ByVal e As System.EventArgs) Handles Socket.OnRead<br/>
Dim strPeerAddress As String = String.Empty
Dim nPeerPort As Integer = 0<br/>
Dim msgBuffer(8192) As Byte<br/>
Dim nBytesRead As Integer<br/>
Dim nBytesWritten As Integer<br/>
Dim LengthOfStru As Integer
<br/>
The OnRead event will fire whenever a remote host sends a datagram to<br/>
us on the port number that was specified. In this example, we limit<br/>
the size of the datagram to 8K, but this could be any value up to 64K
Initialize the contents of the byte array
<br/>
Array.Clear(msgBuffer, 0, 8192)
Read the datagram that was sent to us; if the datagram is larger than<br/>
the maxiumum size of our buffer, the remaining data is discarded<br/>
nBytesRead = Socket.ReadFrom(msgBuffer, 8192, strPeerAddress, nPeerPort)<br/>
Debug.Print(String.Format("nBytesRead = {0}", nBytesRead))<br/>
If nBytesRead = -1 Then<br/>
UpdateListBox(String.Format("Error {0}: {1}", Socket.LastError, Socket.LastErrorString))<br/>
Exit Sub<br/>
End If
If nBytesRead > 0 Then<br/>
Echo the datagram back to the remote host that sent it to us<br/>
nBytesWritten = Socket.WriteTo(msgBuffer, nBytesRead, strPeerAddress, nPeerPort)<br/>
UpdateListBox(String.Format("Read {0} bytes of data", nBytesRead))<br/>
For Index As Int16 = 0 To nBytesRead<br/>
Debug.Print(String.Format("msgBuffer = {0}-{1}", Index, Conversion.Hex(msgBuffer(Index))))<br/>
Next<br/>
Start here<br/>
convert to bytes<br/>
With Tst<br/>
Debug.Print(.ActSpeed, .ActStripLength, .StripSetThick, .ExitStripID, .ActFlatAct)
End With<br/>
LengthOfStru = Len(Tst)<br/>
LengthOfStru = Marshal.SizeOf(Tst)<br/>
Call BulidStr method to create structure
<br/>
and copy byte array data to structure<br/>
Tst = ConvertBytesToStructure(msgBuffer, Tst.GetType)<br/>
Now use it and print it<br/>
Debug.WriteLine(Tst.ActSpeed.ToString)<br/>
Debug.WriteLine(Tst.SeqCount.ToString)
If nBytesWritten = -1 Then<br/>
UpdateListBox(String.Format("Error {0}: {1}", Socket.LastError, Socket.LastErrorString))<br/>
Exit Sub<br/>
End If<br/>
End If
End Sub
End Class
View the full article
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri I have been working on changing old VB6 code over to VB2010. VB6 program receives UDP byte data that is send from real time computer
system then moves the data into a VB6 TYPE (structure) for storage into database and display system. Now Iâm trying to do the same thing in 2010 but I keep getting an System.AccessViolationException error when I try to run a sample code from MSDN an
function called ConvertBytesToStructure. Below is the code I put together. It may be that I donât have the structure created correctly. Please help.
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-family:Calibri; font-size:small
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri Thanks
<p style="line-height:normal; margin:0in 0in 0pt <span style=" <span style="font-size:small <span style="font-family:Calibri Don
<br/>
Option Strict Off<br/>
Option Explicit On
Imports SocketTools<br/>
Imports SocketTools.SocketWrench<br/>
Imports System.Runtime.InteropServices<br/>
Imports System.Text
Public Class Form1
Inherits System.Windows.Forms.Form
Private WithEvents Socket As New SocketTools.SocketWrench
This the orginal VB6 TYPE Structure<br/>
----------------------------------------------------------------------<br/>
Private Type tcsDataType Real data coming from TM TCS System<br/>
MsgID As Long DINT<br/>
SeqCount As Long {DINT}<br/>
QDIntelSysCntr As Long {DWORD}<br/>
StripID As String * 10 in TCS as StripID(0 To 9) As Byte<br/>
ExitStripID As String * 10 in TCS as StripID(0 To 9) As Byte<br/>
StripWidth As Single<br/>
StripSetThick As Single<br/>
ActStripLength As Single<br/>
ActSpeed As Single<br/>
ActFlatAct(0 To 53) As Single<br/>
End Type
Private fromData As tcsDataType<br/>
Private sendData As tcsDataType<br/>
Private fromBuffer(524) As Byte Was 272<br/>
Private sendBuffer(264) As Byte Was 272<br/>
----------------------------------------------------------------------
<br/>
Private Structure tcsDataStructure<br/>
Dim MsgID As Int32<br/>
Dim SeqCount As Int32<br/>
Dim QDIntelSysCntr As Int32<br/>
Dim StripID() As Byte<br/>
Dim ExitStripID() As Byte<br/>
Dim StripWidth As Single<br/>
Dim StripSetThick As Single<br/>
Dim ActStripLength As Single<br/>
Dim ActSpeed As Single<br/>
Dim ActFlatAct() As Single<br/>
End Structure
Dim ByteClear() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}<br/>
Dim FlatClear() As Single = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,<br/>
0.0, 0.0, 0.0, 0.0}<br/>
Dim Tst As New tcsDataStructure With {.MsgID = 0,<br/>
.SeqCount
= 0,<br/>
.QDIntelSysCntr
= 0,<br/>
.StripID =
ByteClear,<br/>
.ExitStripID
= ByteClear,<br/>
.StripWidth
= 0.0,<br/>
.StripSetThick
= 0.0,<br/>
.ActStripLength
= 0.0,<br/>
.ActSpeed
= 0.0,<br/>
.ActFlatAct
= FlatClear}
Function to Create structure must be called first<br/>
Private Function BulidStr(ByVal Buff() As Byte, ByVal MyType As System.Type) As Object<br/>
Dim MyGC As GCHandle = GCHandle.Alloc(Buff, GCHandleType.Pinned)<br/>
Marshals data from an unmanaged block of memory to a newly<br/>
allocated managed object of the specified type.<br/>
Dim Obj As Object = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyType)<br/>
Return Obj<br/>
Free GChandle to avoid memory leaks<br/>
MyGC.Free()<br/>
End Function
Private Function ConvertBytesToStructure(ByVal data() As Byte, ByVal struct As System.Type) As tcsDataStructure<br/>
Create an unmanaged handle to the data array
<br/>
Dim gc As GCHandle<br/>
Try<br/>
gc = GCHandle.Alloc(data, GCHandleType.Pinned)<br/>
Marshal the data at the pointer address into the structure specified
<br/>
Dim obj As tcsDataStructure = DirectCast(Marshal.PtrToStructure(gc.AddrOfPinnedObject, struct), tcsDataStructure)<br/>
Return the object created by the PtrToStructure call
<br/>
Return obj<br/>
Finally<br/>
gc.Free()<br/>
End Try
End Function
Private Sub UpdateListBox(ByVal message As String)<br/>
ListBox1.Items.Add(message)<br/>
ListBox1.SelectedIndex = ListBox1.Items.Count - 1<br/>
ListBox1.ClearSelected()<br/>
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click<br/>
Dim strLocalAddress As String<br/>
Dim nLocalPort As Integer
strLocalAddress = TextBox1.Text.Trim()<br/>
If strLocalAddress.Length = 0 Then<br/>
strLocalAddress = "0.0.0.0"<br/>
End If
nLocalPort = Int32.Parse(TextBox2.Text)<br/>
If nLocalPort < 1 Or nLocalPort > 65535 Then<br/>
MsgBox("Please specify a valid local port number", MsgBoxStyle.Exclamation, "Error")<br/>
Exit Sub<br/>
End If
If the Handle property is -1, this means that the UDP socket has not been<br/>
created. Initialize the socket properties and create a datagram socket<br/>
using the Bind method. By setting Blocking to false, the OnRead event will<br/>
be raised when a remote host sends us a datagram.<br/>
If Socket.Handle = -1 Then<br/>
Socket.Protocol = SocketProtocol.socketDatagram<br/>
Socket.Blocking = False
Bind to the specified IP address and port number<br/>
If Not Socket.Bind(strLocalAddress, nLocalPort) Then<br/>
MsgBox(Socket.LastErrorString, MsgBoxStyle.Exclamation, "Error")<br/>
Exit Sub<br/>
End If<br/>
Button1.Text = "Stop"<br/>
UpdateListBox(String.Format("Started listening for datagrams on {0}:{1}", strLocalAddress, nLocalPort))<br/>
Else<br/>
Close the datagram socket using the Disconnect method<br/>
Socket.Disconnect()<br/>
Button1.Text = "Start"<br/>
UpdateListBox("Stopped listening for datagrams")<br/>
End If
End Sub
Private Sub Socket_OnRead(ByVal sender As Object, ByVal e As System.EventArgs) Handles Socket.OnRead<br/>
Dim strPeerAddress As String = String.Empty
Dim nPeerPort As Integer = 0<br/>
Dim msgBuffer(8192) As Byte<br/>
Dim nBytesRead As Integer<br/>
Dim nBytesWritten As Integer<br/>
Dim LengthOfStru As Integer
<br/>
The OnRead event will fire whenever a remote host sends a datagram to<br/>
us on the port number that was specified. In this example, we limit<br/>
the size of the datagram to 8K, but this could be any value up to 64K
Initialize the contents of the byte array
<br/>
Array.Clear(msgBuffer, 0, 8192)
Read the datagram that was sent to us; if the datagram is larger than<br/>
the maxiumum size of our buffer, the remaining data is discarded<br/>
nBytesRead = Socket.ReadFrom(msgBuffer, 8192, strPeerAddress, nPeerPort)<br/>
Debug.Print(String.Format("nBytesRead = {0}", nBytesRead))<br/>
If nBytesRead = -1 Then<br/>
UpdateListBox(String.Format("Error {0}: {1}", Socket.LastError, Socket.LastErrorString))<br/>
Exit Sub<br/>
End If
If nBytesRead > 0 Then<br/>
Echo the datagram back to the remote host that sent it to us<br/>
nBytesWritten = Socket.WriteTo(msgBuffer, nBytesRead, strPeerAddress, nPeerPort)<br/>
UpdateListBox(String.Format("Read {0} bytes of data", nBytesRead))<br/>
For Index As Int16 = 0 To nBytesRead<br/>
Debug.Print(String.Format("msgBuffer = {0}-{1}", Index, Conversion.Hex(msgBuffer(Index))))<br/>
Next<br/>
Start here<br/>
convert to bytes<br/>
With Tst<br/>
Debug.Print(.ActSpeed, .ActStripLength, .StripSetThick, .ExitStripID, .ActFlatAct)
End With<br/>
LengthOfStru = Len(Tst)<br/>
LengthOfStru = Marshal.SizeOf(Tst)<br/>
Call BulidStr method to create structure
<br/>
and copy byte array data to structure<br/>
Tst = ConvertBytesToStructure(msgBuffer, Tst.GetType)<br/>
Now use it and print it<br/>
Debug.WriteLine(Tst.ActSpeed.ToString)<br/>
Debug.WriteLine(Tst.SeqCount.ToString)
If nBytesWritten = -1 Then<br/>
UpdateListBox(String.Format("Error {0}: {1}", Socket.LastError, Socket.LastErrorString))<br/>
Exit Sub<br/>
End If<br/>
End If
End Sub
End Class
View the full article