Обаждането WriteFile() работи на x86, но не и на x64. Получаване на код за грешка 6 Манипулаторът е невалиден при използване на VB.NET

Използвам извиквания на API CreateFile, WriteFile и ReadFile, за да запиша някои данни на USB устройство. Кодът, който имам, работи перфектно на 32-битови системи. CreateFile получава манипулатор на устройството, предава този манипулатор и някои данни на WriteFile и чете от този манипулатор с ReadFile.

Проблемът ми е, че същият код не работи на 64 битова система. Грешката, върната от WriteFile, е 6, манипулаторът е невалиден. Проверих дръжката за валидност на извикването CreateFile и тя е валидна дръжка. Извикването на GetLastError() връща 0 след CreateFile. „Файлът“ се отваря за припокриваща се комуникация и припокриващите се 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

Следва кодът за запис, където възниква проблемът. Трябва да се отбележи, че при четенето параметърът 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 postfix - само за безопасност. Показване на дефиницията на 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. При стартиране на програмата, когато за първи път отворя порта, изчиствам I/O буферите
  2. След това записвам знак 0x00 (нулев) в самия порт, използвайки WriteFile, за да го инициализирам.

И БИНГО работи. Оттогава не съм имал проблеми.

person Jack    schedule 02.02.2011

Защо просто не използвате NativeOverlapped? Той е специално проектиран за тази задача.

person user541686    schedule 21.01.2011