2010-09-20 34 views
0

J'utilise les appels d'API CreateFile, WriteFile et ReadFile pour écrire des données sur un périphérique USB. Le code que j'ai fonctionne parfaitement sur les systèmes 32 bits. CreateFile obtient un handle sur le périphérique, transmet ce handle et des données à WriteFile et lit à partir de ce handle avec ReadFile.L'appel WriteFile() fonctionne sur x86, mais pas sur x64. Obtenir le code d'erreur 6 - Le handle n'est pas valide en utilisant VB.NET

Mon problème est, le même code ne fonctionne pas sur un système 64 bits. L'erreur renvoyée par WriteFile est 6, Le handle est invalide. J'ai vérifié la validité du handle sur l'appel CreateFile et c'est un handle valide. Un appel à GetLastError() renvoie 0 après CreateFile. Le "fichier" est en cours d'ouverture pour une communication avec chevauchement et les appels d'initialisation superposés retournent également leurs propres valeurs.

Ma question: est-ce qu'il y a une sorte de considération différente que je dois faire parce que c'est un système 64 bits? Un drapeau différent? Un appel différent? Juste pour noter, j'ai fait un peu un hack sur le code pour le rendre synchrone (a enlevé le OVERLAPPED) et cela a fonctionné, donc je suppose que le problème est dans ma structure OVERLAPPED ou la manière dont je suis m initialiser les appels.

Toute aide est grandement appréciée.

Edit:

Voici mes signatures API et le code que je me sers pour ma mise en œuvre CHEVAUCHEMENT

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 

Ce qui suit est le code pour l'écriture, où le problème se produit. Il convient de noter que dans la lecture, le paramètre hEvent de structure OVERLAPPED est initialisé de la même façon

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 
+1

Une chance de voir votre code? –

+0

Je viens d'éditer mon post avec le code correspondant. – Brandon

+1

N'utilisez pas Boolean pour le type BOOL. Int32 BOOL est une valeur de 32 bits, utilise int ou Int32. Pour toutes les fonctions avec des paramètres de chaîne, définissez explicitement MarshalAs et utilisez postfix A ou W en conséquence - juste pour la sécurité. Afficher la définition PInvoke de la structure OVERLAPPED. –

Répondre

1

J'ai eu le même problème ... J'ai trouvé que l'erreur de handle non valide a disparu quand je mis le doigt explicitement la structure chevauchée :

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 

Bonne chance.

1

J'ai eu exactement le même problème. Mêmes symptômes Je l'ai fixé par

  1. Au démarrage du programme quand je d'abord ouvrir le port I purger les entrées/sorties des tampons
  2. I puis d'écrire un caractère de 0x00 (null) au port lui-même en utilisant WriteFile pour l'initialiser.

Et BINGO cela fonctionne. Je n'ai pas eu de problèmes depuis.