none
Converting vba to vb.net getting error with a function RRS feed

  • Question

  • I have a program that was created in vba, and I am working on converting it to VB.net. I have managed to get most of it working, but I am having issues with converting one function right now.
    The function in vba is:

    Private Function OpenPort(CommPort As Integer, CommSettings As String) As LongPtr
    
        Dim CommDCB As DCB
        Dim status As Long
        Dim Handle As LongPtr
        Dim timeOuts As commTimeOuts
          
        ' Open port
        Handle = CreateFile("\\.\COM" + Trim(Str(CommPort)), &HC0000000, 0, Null, 3, &H80, 0)
        MsgBox (Handle)
        If Handle = -1 Then
            OpenPort = -1
        Else
        
            'Try to apply settings to the port
            status = GetCommState(Handle, CommDCB)
            If status = 0 Then
                ClosePort (Handle)
                OpenPort = -1
                Exit Function
            End If
            
            status = BuildCommDCB(CommSettings, CommDCB)
            If status = 0 Then
                ClosePort (Handle)
                OpenPort = -1
                Exit Function
            End If
            
            status = SetCommState(Handle, CommDCB)
            If status = 0 Then
                ClosePort (Handle)
                OpenPort = -1
                Exit Function
            End If
            
            With timeOuts
                .ReadIntervalTimeout = -1
                .ReadTotalTimeoutMultiplier = 0
                .ReadTotalTimeoutConstant = 500
                .WriteTotalTimeoutMultiplier = 0
                .WriteTotalTimeoutMultiplier = 500
            End With
            
            status = SetCommTimeouts(Handle, timeOuts)
             If status = 0 Then
                ClosePort (Handle)
                OpenPort = -1
                Exit Function
            End If
            
            OpenPort = Handle
            
        End If
        
    End Function

    The error I am getting with the changes to make it work in vb.net is "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'"
    The error is on the line

    status = Relay_Functions.GetCommState(Handle, CommDCB)

    I have changed the line to create the handle as such:

    Handle = Relay_Functions.CreateFile("\\.\COM" + Trim(Str(CommPort)), &HC0000000, 0, Nothing, 3, &H80, 0)

    I have changed the longs to integers as well throughout the function as well. I'm thinking the error is with Trim(Str(CommPort)), but I'm not fully sure that is correct, as I haven't been able to get anything that doesn't throw the error and have it work correctly yet.


    Monday, February 5, 2018 5:40 PM

All replies

  • Hello,

    Usually its better to not bring any code from the vba code but instead start with .NET Framework classes e,g

    https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Monday, February 5, 2018 6:09 PM
    Moderator
  • The sentence "This is often an indication that other memory is corrupt." is the most uncommercial message Microsoft keeps using for years.

    https://www.vocabulary.com/dictionary/corruption


    The chance is high that VB for net tries to access an area of the memory which is blocked for instance by defender. (It does not mean the memory is damaged). 

    However,  make it yourself easy, tell what you want to do because this VBA way has probably smoother solutions in VB using the serial class for instance on this page.

    https://docs.microsoft.com/en-us/dotnet/visual-basic/developing-apps/programming/computer-resources/how-to-receive-strings-from-serial-ports


    Success Cor

    Monday, February 5, 2018 6:12 PM
  • This looks like Windows API for serial communications (you didn't include the API declarations), which will require p-invoke. The below project should help you convert the code to .NET and fix your API declarations:

    https://www.codeproject.com/Articles/5131/COM-port-made-simple-with-VB-NET


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Monday, February 5, 2018 6:34 PM
  • That is correct this is for controlling a usb relay.

    I didn't include them but in the program I also have:

    Structure DCB Public DCBlength As Integer Public BaudRate As Integer Public fBitFields As Integer Public wReserved As Integer Public XonLim As Integer Public XoffLim As Integer Public ByteSize As Byte Public Parity As Byte Public StopBits As Byte Public XonChar As Byte Public XoffChar As Byte Public ErrorChar As Byte Public EofChar As Byte Public EvtChar As Byte Public wReserved1 As Integer End Structure Structure commTimeOuts Public ReadIntervalTimeout As Integer Public ReadTotalTimeoutMultiplier As Integer Public ReadTotalTimeoutConstant As Integer Public WriteTotalTimeoutMultiplier As Integer Public WriteTotalTimeoutConstant As Integer End Structure

        Class Relay_Functions
            Public Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" (ByVal lpDef As String, lpDCB As DCB) As Integer
            Public Declare Function SetCommState Lib "kernel32" (ByVal hFile As Integer, lpDCB As DCB) As Integer
            Public Declare Function GetCommState Lib "kernel32" (ByVal hFile As Integer, lpDCB As DCB) As Integer
            Public Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Integer, lpCommTimeouts As commTimeOuts) As Integer
            Public Declare Function CloseHandle Lib "kernel32" (ByVal hFile As Integer) As Integer
            Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As Integer) As Integer
            Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByVal lpBuffer As Integer, ByVal nNumberOfBytesToRead As Integer, lpNumberOfBytesRead As Integer, ByVal lpOverlapped As Integer) As Integer
            Public Declare Function WriteFile Lib "kernel32" (ByVal hFile As Integer, ByVal lpBuffer As Integer, ByVal nNumberOfBytesToWrite As Integer, lpNumberOfBytesWritten As Integer, ByVal lpOverlapped As Integer) As Integer
            Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)
        End Class


    Monday, February 5, 2018 6:41 PM
  • You need to double-check some of your API function call Declaration statements. I'm not seeing ByRef for the DCB structure:

        Inherits MarshalByRefObject
    
        <DllImport("kernel32.dll")> Private Shared Function CreateFile( _
               <MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String, _
               ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, _
               ByVal lpSecurityAttributes As Integer, _
               ByVal dwCreationDisposition As Integer, _
               ByVal dwFlagsAndAttributes As Integer, _
               ByVal hTemplateFile As Integer) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function GetCommState( _
            ByVal hCommDev As Integer, ByRef lpDCB As DCB) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function ReadFile( _
        ByVal hFile As Integer, ByVal Buffer As Byte(), _
        ByVal nNumberOfBytesToRead As Integer, _
        ByRef lpNumberOfBytesRead As Integer, _
        ByRef lpOverlapped As OVERLAPPED) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function SetCommState( _
        ByVal hCommDev As Integer, ByRef lpDCB As DCB) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function WriteFile( _
        ByVal hFile As Integer, ByVal Buffer As Byte(), _
        ByVal nNumberOfBytesToWrite As Integer, _
        ByRef lpNumberOfBytesWritten As Integer, _
        ByRef lpOverlapped As OVERLAPPED) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function CloseHandle( _
                ByVal hObject As Integer) As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function GetLastError() As Integer
        End Function
    
        <DllImport("kernel32.dll")> Private Shared Function BuildCommDCB( _
            ByVal lpDef As String, ByRef lpDCB As DCB) As Integer
        End Function


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Monday, February 5, 2018 6:59 PM
  • Adding those managed to get rid of the error, but for some reason now when I go to turn on the relay nothing happens.

            DeviceHandle = OpenPort(4, "baud=19200 parity=N data=8 stop=1 dtr=Off xon=off to=off odsr=off octs=off rts=off idsr=off")
            status = CommWrite(DeviceHandle, "relay on " + Trim(3) + Chr(13))
            Threading.Thread.Sleep(1000)
            ClosePort(DeviceHandle)

    I'll have to play around with it some now though, and see if I can figure it out.
    Monday, February 5, 2018 7:39 PM
  •  Actually,  the CreateFile function returns a Handle which should be an IntPtr type in Vb.Net.  The other functions that require that returned handle are also suppose to be declared as IntPtr types too.  Just figured it was worth mentioning.  8)


    If you say it can`t be done then i`ll try it

    Monday, February 5, 2018 7:58 PM
  • Adding those managed to get rid of the error, but for some reason now when I go to turn on the relay nothing happens.

            DeviceHandle = OpenPort(4, "baud=19200 parity=N data=8 stop=1 dtr=Off xon=off to=off odsr=off octs=off rts=off idsr=off")
            status = CommWrite(DeviceHandle, "relay on " + Trim(3) + Chr(13))
            Threading.Thread.Sleep(1000)
            ClosePort(DeviceHandle)

    I'll have to play around with it some now though, and see if I can figure it out.

    Why don't you try VB.Net serial communications?

    SerialPort Class

    Serial Port Communication in VB.Net


    La vida loca

    Monday, February 5, 2018 8:03 PM
  •  Actually,  the CreateFile function returns a Handle which should be an IntPtr type in Vb.Net.  The other functions that require that returned handle are also suppose to be declared as IntPtr types too.  Just figured it was worth mentioning.  8)


    If you say it can`t be done then i`ll try it


    Hola Razerz!

    La vida loca

    Monday, February 5, 2018 8:03 PM
  • The sentence "This is often an indication that other memory is corrupt." is the most uncommercial message Microsoft keeps using for years.

    https://www.vocabulary.com/dictionary/corruption


    The chance is high that VB for net tries to access an area of the memory which is blocked for instance by defender. (It does not mean the memory is damaged). 

    However,  make it yourself easy, tell what you want to do because this VBA way has probably smoother solutions in VB using the serial class for instance on this page.

    https://docs.microsoft.com/en-us/dotnet/visual-basic/developing-apps/programming/computer-resources/how-to-receive-strings-from-serial-ports


    Success Cor


    Hola Cor!

    La vida loca

    Monday, February 5, 2018 8:03 PM