【问题标题】:WriteFile() call works on x86, but not x64. Getting error code 6 -- The handle is invalid using VB.NETWriteFile() 调用适用于 x86,但不适用于 x64。获取错误代码 6 -- 使用 VB.NET 时句柄无效
【发布时间】:2010-09-20 16:04:25
【问题描述】:

我正在使用 CreateFile、WriteFile 和 ReadFile API 调用将一些数据写入 USB 设备。我的代码在 32 位系统上运行良好。 CreateFile 获取设备的句柄,将该句柄和一些数据传递给 WriteFile 并使用 ReadFile 从该句柄中读取。

我的问题是,相同的代码在 64 位系统上不起作用。 WriteFile 返回的错误为 6,句柄无效。我在 CreateFile 调用中检查了句柄的有效性,它是一个有效的句柄。在 CreateFile 之后调用 GetLastError() 将返回 0。正在为重叠通信打开“文件”,并且重叠的 init 调用也正在返回它们的正确值。

我的问题:由于它是 64 位系统,我需要考虑一些不同的因素吗?不同的旗帜?完全不同的电话?

请注意,我对代码进行了一些修改以使其同步(取出 OVERLAPPED)并且它起作用了,所以我假设问题出在我的 OVERLAPPED 结构或我的方式上初始化调用。

非常感谢任何帮助。

编辑:

以下是我的 API 签名和我用于 OVERLAPPED 实现的代码

Private Declare Auto Function CreateFile Lib "kernel32.dll" _
                                    (ByVal lpFileName As String, _
                                    ByVal dwDesiredAccess As Integer, _
                                    ByVal dwShareMode As Integer, _
                                    ByVal lpSecurityAttributes As IntPtr, _
                                    ByVal dwCreationDisposition As Integer, _
                                    ByVal dwFlagsAndAttributes As Integer, _
                                    ByVal hTemplateFile As IntPtr) As IntPtr


Private Declare Auto Function WriteFile Lib "kernel32.dll" _
                                    (ByVal hFile As IntPtr, ByVal Buffer As Byte(), _
                                    ByVal nNumberOfBytesToWrite As Integer, _
                                    ByRef lpNumberOfBytesWritten As Integer, _
                                    ByRef lpOverlapped As OVERLAPPED) As Boolean

Private Declare Auto Function ReadFile Lib "kernel32.dll" _
                                    (ByVal hFile As IntPtr, _
                                    ByVal Buffer As Byte(), _
                                    ByVal nNumberOfBytesToRead As Integer, _
                                    ByRef lpNumberOfBytesRead As Integer, _
                                    ByRef lpOverlapped As OVERLAPPED) As Boolean

Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal hFile As IntPtr) As Boolean

Private Declare Auto Function CancelIo Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean

Private Declare Auto Function GetOverlappedResult Lib "kernel32.dll" ( _
                                    ByVal hFile As IntPtr, ByRef lpOverlapped As OVERLAPPED, _
                                    ByRef lpNumberOfBytesTransferred As Integer, _
                                    ByVal bWait As Boolean) As Boolean

Private Declare Auto Function CreateEvent Lib "kernel32.dll" ( _
                                    ByVal lpEventAttributes As Integer, ByVal bManualReset As Boolean, _
                                    ByVal bInitialState As Boolean, _
                                    <MarshalAs(UnmanagedType.LPStr)> ByVal lpName As String) As IntPtr

Private Declare Auto Function WaitForSingleObject Lib "kernel32.dll" ( _
                                    ByVal hHandle As IntPtr, ByVal dwMilliseconds As Integer) As Integer

以下是出现问题的写入代码。需要注意的是,在读取中,OVERLAPPED结构的hEvent参数也是以同样的方式初始化的

Try

        With IOStructure
            .overlap.hEvent = CreateEvent(Nothing, True, False, Nothing)
            If .overlap.hEvent = 0 Then
                writeSuccess = False
            Else
                writeSuccess = WriteFile(.hdevice, .writeBuf, .writeBuf.Length, .bytesWritten, .overlap)

                'If the write didn't succeed, check to see if it's pending
                If Not writeSuccess Then

                    If Err.LastDllError <> ERROR_IO_PENDING Then 'The write failed
                        writeSuccess = False
                    Else ' Write is pending

                        Select Case WaitForSingleObject(.overlap.hEvent, .timeout * 0.1) 'Wait for the write to complete

                            Case 0 'The write completed, check the overlapped structure for the signalled event.
                                writeSuccess = GetOverlappedResult(.hdevice, .overlap, .bytesWritten, 0)
                            Case Else
                                writeSuccess = False
                        End Select
                    End If

                End If
            End If
            CloseHandle(.overlap.hEvent)
        End With
        '   Thread.Sleep(IOStructure.timeout * 0.3)
        ' End While
    Catch
        writeSuccess = False
    End Try

【问题讨论】:

  • 我刚刚用相关代码编辑了我的帖子。
  • 不要将布尔值用于 BOOL 类型。 Int32 BOOL 是 32 位值,使用 int 或 Int32。对于所有带有字符串参数的函数,显式定义 MarshalAs 并相应地使用 A 或 W 后缀 - 只是为了安全。显示 OVERLAPPED 结构的 PInvoke 定义。
  • 我会做出改变并告诉你它是如何工作的,谢谢。

标签: createfile overlapped-io


【解决方案1】:

我遇到了同样的问题...我发现当我显式将重叠结构归零时,无效句柄错误消失了:

Dim ovl As OVERLAPPED
static ovlRead As IntPtr = Nothing

' Marshal (allocate unmanaged) structure only once
If IsNothing(ovlRead) then
    ovlRead = Marshal.AllocHGlobal(Marshal.SizeOf(ovl))

    Marshal.WriteInt32(ovlRead, 0, 0)
    Marshal.WriteInt32(ovlRead, 4, 0)
    Marshal.WriteInt32(ovlRead, 8, 0)
    Marshal.WriteInt32(ovlRead, 12, 0)
    Marshal.WriteInt32(ovlRead, 16, 0)
End If

祝你好运。

【讨论】:

    【解决方案2】:

    我遇到了完全相同的问题。相同的症状。我通过

    修复了它
    1. 在程序启动时,当我第一次打开端口时,我会清除 I/O 缓冲区
    2. 然后我使用 WriteFile 将 0x00(空)字符写入端口本身以对其进行初始化。

    而且 BINGO 它有效。从那以后就没有问题了。

    【讨论】:

      【解决方案3】:

      你为什么不直接使用NativeOverlapped?它专为此任务而设计。

      【讨论】:

        猜你喜欢
        • 2023-04-10
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多