Вызов WriteFile() работает на x86, но не на x64. Получение кода ошибки 6 Дескриптор недействителен при использовании VB.NET

Я использую вызовы API CreateFile, WriteFile и ReadFile для записи некоторых данных на USB-устройство. Код, который у меня есть, отлично работает на 32-битных системах. CreateFile получает дескриптор устройства, передает этот дескриптор и некоторые данные в WriteFile и читает из этого дескриптора с помощью ReadFile.

Моя проблема в том, что тот же код не работает в 64-битной системе. Ошибка, возвращенная из WriteFile, равна 6, дескриптор недействителен. Я проверил правильность дескриптора вызова CreateFile, и это действующий дескриптор. Вызов GetLastError() возвращает 0 после CreateFile. «Файл» открывается для перекрывающейся связи, и перекрывающиеся вызовы инициализации также возвращают свои правильные значения.

Мой вопрос: есть ли какое-то другое соображение, которое мне нужно сделать, потому что это 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

Ниже приведен код записи, в которой возникает проблема. Следует отметить, что при чтении параметр hEvent структуры OVERLAPPED инициализируется таким же образом.

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

person Brandon    schedule 20.09.2010    source источник
comment
Я только что отредактировал свой пост с соответствующим кодом.   -  person Brandon    schedule 20.09.2010
comment
Не используйте Boolean для типа BOOL. Int32 BOOL — это 32-битное значение, используйте int или Int32. Для всех функций со строковыми параметрами явно определите MarshalAs и используйте постфикс A или W соответственно — просто для безопасности. Показать определение PInvoke структуры OVERLAPPED.   -  person Alex F    schedule 21.09.2010
comment
Я внесу это изменение и дам вам знать, как оно работает, спасибо.   -  person Brandon    schedule 22.09.2010


Ответы (3)


У меня была та же проблема... Я обнаружил, что ошибка недопустимого дескриптора исчезла, когда я явно обнулил перекрывающуюся структуру:

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

Удачи.

person Rich_B    schedule 03.12.2010

У меня была точно такая же проблема. Те же симптомы. Я исправил это

  1. При запуске программы, когда я впервые открываю порт, я очищаю буферы ввода-вывода.
  2. Затем я записываю символ 0x00 (нулевой) в сам порт, используя WriteFile для его инициализации.

И БИНГО это работает. С тех пор проблем не было.

person Jack    schedule 02.02.2011

Почему бы вам просто не использовать NativeOverlapped? Он специально разработан для этой задачи.

person user541686    schedule 21.01.2011