0

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
4

3 に答える 3

1

私はまったく同じ問題を抱えていました。同じ症状。で修正しました

  1. プログラムの起動時に最初にポートを開いたときに、I/Oバッファをパージします
  2. 次に、WriteFileを使用してポート自体に0x00(null)文字を書き込んで初期化します。

そしてビンゴそれは動作します。それ以来、問題は発生していません。

于 2011-02-02T00:01:19.927 に答える
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

幸運を。

于 2010-12-03T07:41:34.017 に答える
0

NativeOverlappedを使ってみませんか?このタスクのために特別に設計されています。

于 2011-01-21T22:21:39.683 に答える