【问题标题】:vb.net AccessViolationException and FatalExecutionEngineErrorvb.net AccessViolationException 和 FatalExecutionEngineError
【发布时间】:2016-01-13 16:16:37
【问题描述】:

我已经在这个项目上工作了一周左右,在一周的开始,我的 ReadFile 返回了 AccessViolationException - “尝试读取或写入受保护的内存。”所以我玩了一下它,它就消失了。我以为我修好了,但也许没有?现在我的 WriteFile 抛出了一个 FatalExecutionEngineError,经过一番阅读,这两个事件似乎是相关的;不过我不确定。这是我的声明,这些可能有问题:

    <DllImport("kernel32.dll")> Private Shared Function CloseHandle(
    ByVal hObject As Integer) As Integer
End Function

<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 GetCommTimeouts(
    ByVal hFile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) As Integer
End Function

<DllImport("kernel32.dll")> Private Shared Function GetLastError() As Integer
End Function

<DllImport("kernel32.dll")> Private Shared Function PurgeComm(
    ByVal hFile As Integer, ByVal dwFlags As Integer) 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 SetCommTimeouts(
    ByVal hFile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) 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 SetCommMask(
    ByVal hFile As Integer,
    ByVal dwEvtMask As Integer) As Integer
End Function

<DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function WaitCommEvent(
    ByVal hFile As Integer,
    ByRef mask As Integer,
    ByRef lpOverlap As Overlapped) As Integer
End Function

<DllImport("kernel32.dll")> Private Shared Function FormatMessage(
    ByVal dwFlags As Integer,
    ByVal lpSource As Integer,
    ByVal dwMessageId As Integer,
    ByVal dwLanguageId As Integer,
    ByVal lpBuffer As StringBuilder,
    ByVal nSize As Integer,
    ByVal Arguments As Integer) As Integer
End Function

这里是最初导致 AccessViolationException 的代码,它消失了:

Private Function read() As String
    Dim sErrTxt As String
    Dim iReadChars, iRc As Integer

    If mhRS <> INVALID_HANDLE_VALUE Then
        ' Sets Comm Mask
        iRc = SetCommMask(mhRS, EventMasks.RxChar)
        If iRc <> 0 Then
            'Waits for a comm event
            iRc = WaitCommEvent(mhRS, miEvtMask, Nothing)
            If iRc <> 0 Then
                miStringSize = 0
                miString = ""
                ReDim mabtRxBuf(miBufferSize)
                ' Loop through the buffer and store it in a string while there is still chars in the buffer
                For i As Integer = 0 To 20
                    iRc = ReadFile(mhRS, mabtRxBuf, miBufferSize, iReadChars, Nothing)
                    If iRc <> 0 Then
                        ' Stores the size of the string read and forms the string
                        If iReadChars > 0 Then
                            miStringSize += iReadChars
                            miString &= defaultEncoding.GetString(mabtRxBuf)
                        End If
                    Else
                        ' Read Error 
                        sErrTxt = pErr2Text(GetLastError())
                        MsgBox("ReadFile failed " & sErrTxt)
                        Return Nothing
                    End If
                Next
                'Loop While iReadChars > 0
                ' Returns the concantenated string
                Return miString
            Else
                ' Handles WaitCommEvent error
                sErrTxt = pErr2Text(GetLastError())
                MsgBox("WaitCommEvent failed " & sErrTxt)
                Return Nothing
            End If
        Else
            ' Handles SetSommMask error
            sErrTxt = pErr2Text(GetLastError())
            MsgBox("Unable to SetCommMask " & sErrTxt)
            Return Nothing
        End If

    Else
        ' Handles port not open error
        MsgBox("Please initialize port first")
        Return Nothing
    End If
End Function

最后,这里是导致 FatalExecutionEngineError 的代码:

Private Sub write(ByVal byteBuff As Byte())
    Dim sErrTxt As String
    Dim bytesSent = 0, iRc, iWriteChars As Integer

    If mhRS <> INVALID_HANDLE_VALUE Then
        ' Writes the passed Byte() to the comm port
        iRc = WriteFile(mhRS, byteBuff, byteBuff.Length, iWriteChars, Nothing)
        If iRc = 0 Then
            ' Handles WriteFile error
            sErrTxt = pErr2Text(GetLastError())
            MsgBox("WriteFile Failed " & sErrTxt)
        End If
    Else
        ' Handles port not open error
        MsgBox("Please initialize port first")
        Exit Sub
    End If
End Sub

我在 Windows 7 64 位上使用 Visual Studio 2015 和 .NET 4.6.1。我重新安装了.net,但它不起作用,所以我将应用程序转移到另一台机器上,看看它是否可以在那里工作,但它没有。第二台机器和第一台一样。我不知道从这里去哪里。

【问题讨论】:

  • mabtRxBuf 声明在哪里?是否有可能同时被两个线程修改?
  • 我建议您查看pinvoke 网站以确保您拥有推荐的签名。我注意到您正在声明 ReadFile 函数和 Integer 而不是缓冲区的 IntPtr 参数。此外,在调用它时,pinvoke 站点建议使用Marshal.AllocHGlobal 来获取指向缓​​冲区的指针。我不确定这是您问题的原因,但我也不会感到惊讶。
  • 没有什么比缺少 IntPtr 更响亮,水晶球说你没有正确声明 DCB 或 COMMTIMEOUTS。在这种情况下,调用 GetCommState() 或 GetCommTimeouts() 将损坏堆。 最终会导致这次崩溃。只是不要这样做,而是使用 SerialPort 类。
  • @StevenDoggart On pinvoke 它有很多采用 SafeFileHandle 或 IntPtr 的签名,但两者不可互换,那么我在整个签名中使用哪个?
  • @HansPassant 这也可能是我的问题,我会再调查一下。至于 SerialPort 类,它似乎没有实现我需要更改以使设备与我通信的所有参数。每次我尝试使用 SerialPort 类时,我都没有得到设备的响应。

标签: .net vb.net fatal-error access-violation kernel32


【解决方案1】:

最终为我工作的代码:

        Private receivedText As String

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    With miPort
        .PortName = "COM3"
        .BaudRate = 38400
        .Parity = Parity.None
        .StopBits = StopBits.One
        .DataBits = 8
        .DtrEnable = True
        .RtsEnable = True
        .Handshake = Handshake.None
        .Encoding = Encoding.GetEncoding(28591)
    End With
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    If Not miPort.IsOpen Then
        miPort.Open()
    End If

    If miPort.IsOpen Then
        miPort.Write(toCharacters("55FF0510030004BC0105010189D1"))
    End If
End Sub

' Converts the passed string as hexidecimal numbers to its characters
Private Function toCharacters(ByVal hexText As String) As String
    Dim num As String
    Dim sendText As String = ""

    For y As Integer = 1 To Len(hexText) Step 2
        ' Takes two of the numbers passed (1 byte in Hex)
        num = Mid(hexText, y, 2)
        ' Converts the numbers into their decimal number, then to their character and stores them in a String()
        sendText &= (ChrW(Val("&h" & num)))
    Next y

    Return sendText
End Function

Private Sub miPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles miPort.DataReceived
    receivedText = miPort.ReadExisting()
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    相关资源
    最近更新 更多