WriteFile()调用适用于x86,但不适用于x64。获取错误代码6 - 使用VB.NET句柄无效

时间:2010-09-20 16:04:26

标签: createfile overlapped-io

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

我的问题是,相同的代码在64位系统上不起作用。 WriteFile返回的错误是6,句柄无效。我已经在CreateFile调用上检查了句柄的有效性,它是一个有效的句柄。对GetLastError()的调用在CreateFile之后返回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

3 个答案:

答案 0 :(得分: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
祝你好运。

答案 1 :(得分:1)

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

修复了它
  1. 在我第一次打开端口的程序启动时,我清除了I / O缓冲区
  2. 然后我使用WriteFile将一个0x00(null)字符写入端口本身来初始化它。
  3. BINGO它有效。从那时起就没有问题。

答案 2 :(得分:0)

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