Problem mit Windows APIs (WriteFile und ReadFile) suche echten Profi!

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Munich85.

    Problem mit Windows APIs (WriteFile und ReadFile) suche echten Profi!

    Hallo Profis,

    ich wende mich an euch, da ich in Google nun schon die ersten 3-5 Seiten zu jeder erdenklichen Fragestellung in diese Richtung abgearbeitet habe und nicht die Problemlösung finden konnte.

    Ich möchte direkt auf ein USB Laufwerk schreiben und dafür die Windows APIs (CreateFie WriteFile und ReadFile) verwenden.

    CreateFie: Scheint zu funktionieren und gibt mir brav ein Handel auf das gewünschte Laufwerk.

    WriteFile und ReadFile: Sind beim besten Willen nicht dazu zu bewegen, das zu machen wofür Microsoft sie geschrieben hat.


    Ich habe Windows 7 (x64) dies könnte ein Grund für das Problem sein, da einige Alte Codes auf wohl früheren Betriebssystemen wenn man den Postern glauben schenken darf Funktionieren.

    Nun habe ich schon folgendes Versucht:

    - Handel nicht über Buchstabe sondern über:

    '\\.\G:
    'C:\Test\myfile.text
    'USB\VID_058F&PID_6387\58CC7397
    '\\.\PHYSICALDRIVE1
    '\\.\G:\test.avl
    '\\?\Volume{03755169-c62d-11e2-bd6b-001e9086f6bc}\

    - Laufwerk entmounten, Laufwerk sperren, Laufwerk auswerfen. (Da in Tipp dies als Lösung versprochen hat)

    - Schreiben auf File \\.\G\test.txt

    - Schreiben auf C: (vlt liegt es ja am USB-Controller)

    - Diverse andere Schreibweisen der APIs (aus Verzweiflung)

    - Lesen aller Spezifikationen aller verwendeter Funktionen

    Nichts davon hat
    geholfen, deswegen brauche ich den Spezialisten, der mir sagen kann wo das
    Problem ist und ob man es lösen kann. Ich suche hier eine konkrete Antwort auf
    genau diese APIs und nicht benutz doch einfach (My.Computer.FileSystem.WriteAllText()) in einem früheren Problem
    hat sich das nämlich als nicht verwendbar für meine Zwecke herausgestellt.

    Hier Der Quellcode:

    Keine Sorge, das Meiste ist API Deklaration! habs nur der Vollständigkeit halber angehängt um ein einfaches Testen zu ermöglichen, falls jemand eine SUPER Idee hat.

    Danke schon mal! ich hoffe auf eine gute Diskussion :)

    VB.NET-Quellcode

    1. Private Const GENERIC_READ As Integer = &H80000000
    2. Private Const GENERIC_WRITE As Integer = &H40000000
    3. 'Private Const OPEN_EXISTING As Integer = 3
    4. Private Const OPEN_ALWAYS As Integer = 4
    5. Private Const FILE_SHARE_READ As Integer = 1
    6. Private Const FILE_SHARE_WRITE As Integer = 2
    7. Private Const INVALID_HANDLE_VALUE As Integer = -1
    8. 'Private Const FSCTL_LOCK_VOLUME As Integer = &H90018
    9. 'Private Const FSCTL_DISMOUNT_VOLUME As Integer = &H90020
    10. 'Private Const IOCTL_STORAGE_MEDIA_REMOVAL As Integer = &H2D4804
    11. 'Private Const IOCTL_STORAGE_EJECT_MEDIA As Integer = &H2D4808
    12. 'Private Const IOCTL_STORAGE_LOAD_MEDIA As Integer = &H2D480C
    13. 'Private Const FSCTL_ALLOW_EXTENDED_DASD_IO As Integer = &H9000C
    14. Private Const FILE_FLAG_NO_BUFFERING As Integer = &H20000000
    15. Private Const FILE_FLAG_WRITE_THROUGH As Integer = &H80000000
    16. Private Const FILE_BEGIN = 0
    17. Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
    18. ByVal lpFileName As String, _
    19. ByVal dwDesiredAccess As Int32, _
    20. ByVal dwShareMode As Int32, _
    21. ByVal lpSecurityAttributes As IntPtr, _
    22. ByVal dwCreationDisposition As Int32, _
    23. ByVal dwFlagsAndAttributes As Int32, _
    24. ByVal hTemplateFile As IntPtr _
    25. ) As IntPtr
    26. Private Declare Function SetFilePointer Lib "kernel32" ( _
    27. ByVal hFile As IntPtr, _
    28. ByVal lDistanceToMove As Int32, _
    29. ByRef lpDistanceToMoveHigh As Int32, _
    30. ByVal dwMoveMethod As Int32 _
    31. ) As Int32
    32. Private Declare Function ReadFile Lib "kernel32" ( _
    33. ByVal hFile As IntPtr, _
    34. ByRef lpBuffer As IntPtr, _
    35. ByVal nNumberOfBytesToRead As Int32, _
    36. ByRef lpNumberOfBytesRead As Int32, _
    37. ByRef lpOverlapped As IntPtr _
    38. ) As Int32
    39. Private Declare Unicode Function LockFile Lib "kernel32" ( _
    40. ByVal handle As IntPtr, _
    41. ByVal offsetLow As Int32, _
    42. ByVal offsetHigh As Int32, _
    43. ByVal countLow As Int32, _
    44. ByVal countHigh As Int32 _
    45. ) As Int32
    46. Private Declare Function UnlockFile Lib "kernel32" ( _
    47. ByVal hFile As IntPtr, _
    48. ByVal dwFileOffsetLow As Int32, _
    49. ByVal dwFileOffsetHigh As Int32, _
    50. ByVal nNumberOfBytesToUnlockLow As Int32, _
    51. ByVal nNumberOfBytesToUnlockHigh As Int32 _
    52. ) As Int32
    53. Private Declare Function WriteFile Lib "kernel32" ( _
    54. ByVal hFile As IntPtr, _
    55. lpBuffer As IntPtr, _
    56. ByVal nNumberOfBytesToWrite As Int32, _
    57. lpNumberOfBytesWritten As Int32, _
    58. ByVal lpOverlapped As IntPtr _
    59. ) As Int32
    60. Private Declare Function FlushFileBuffers Lib "kernel32" ( _
    61. ByVal hFile As IntPtr _
    62. ) As Int32
    63. Private Declare Function CloseHandle Lib "kernel32" ( _
    64. ByVal hObject As IntPtr _
    65. ) As Int32
    66. Sub MyProblem()
    67. Dim hDevice As IntPtr, retVal As Long, BytesWritten As Long
    68. Dim mybytes(512) As Byte
    69. Dim MY_SECURITY_ATTRIBUTE As IntPtr
    70. Static ovlRead As IntPtr = Nothing
    71. Dim nRead As Long
    72. hDevice = CreateFile("\\.\G:", _
    73. GENERIC_READ Or GENERIC_WRITE, _
    74. FILE_SHARE_READ Or FILE_SHARE_WRITE, _
    75. MY_SECURITY_ATTRIBUTE, _
    76. OPEN_ALWAYS, _
    77. FILE_FLAG_NO_BUFFERING, _
    78. Nothing)
    79. If hDevice = INVALID_HANDLE_VALUE Then Exit Sub
    80. 'Call DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, Nothing, 0, Nothing, 0, lpBuffer, Nothing)
    81. 'Call DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, Nothing, 0, Nothing, 0, lpBuffer, Nothing)
    82. 'Call DeviceIoControl(hDevice, IOCTL_STORAGE_EJECT_MEDIA, Nothing, 0, Nothing, 0, lpBuffer, Nothing)
    83. 'Call DeviceIoControl(hDevice, FSCTL_ALLOW_EXTENDED_DASD_IO, Nothing, 0, Nothing, 0, lpBuffer, Nothing)
    84. Dim R As New System.Random
    85. R.NextBytes(mybytes)
    86. 'Pointer auf Sektor 100
    87. retVal = SetFilePointer(hDevice, 100 * 512, Nothing, FILE_BEGIN)
    88. 'Schreiben
    89. retVal = LockFile(hDevice, 100 * 512, 0, 512, 0)
    90. retVal = WriteFile(hDevice, mybytes(0), 512, nRead, ovlRead)
    91. retVal = FlushFileBuffers(hDevice)
    92. retVal = UnlockFile(hDevice, 100 * 512, 0, 512, 0)
    93. 'Lesen
    94. retVal = ReadFile(hDevice, mybytes(0), 512, nRead, Nothing)
    95. Call CloseHandle(hDevice) End Sub

    Munich85 schrieb:

    Ich suche hier eine konkrete Antwort auf
    genau diese APIs und nicht benutz doch einfach (My.Computer.FileSystem.WriteAllText()) in einem früheren Problem
    hat sich das nämlich als nicht verwendbar für meine Zwecke herausgestellt.
    Ich muss am Schreib-Lesepuffer des USB-Laufwerkes vorbei. Ausserdem würde ich gerne direkt die Sektoren ansprechen.

    Warum ersteres nicht mit WriteAllText() geht siehe

    [VB 2010] Kuriose Codeoptimierung

    Grüße,

    Matthias
    Hast du eine Idee zu dem Problem dieser Funktionen? also warum WriteFile nicht schreiben und ReadFile nicht lesen will?
    Wer was wann wo Puffert und Schreibt ist hier wohl vom USB Controller abhängig, deswegen aber auch Private FILE_FLAG_NO_BUFFERING FILE_FLAG_WRITE_THROUGH und deswegen ebendiese APIs!

    Munich85 schrieb:

    WriteFile ... und ReadFile
    haben nix mit Sektoren zu tun.
    Dafür gab es (unter dem Betriebssystem MS-DOS) Write und Read-Sektor-Befehle, die dürfte es hier auch geben, aber ich glaube nicht, dass die für Dich (uns) sinnvoll zu bedienen sind.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    in der Beschreibung der Funktion: WriteFile

    msdn.microsoft.com/en-us/libra…op/aa365747(v=vs.85).aspx


    ist folgendes zu lesen:

    The following C++ example shows how to align sectors for unbuffered file writes. The Size variable is the size of the original data block you are interested in writing to the file. For additional rules regarding unbuffered file I/O, see File Buffering.



    Auch andere Bespiele beschreiben genau diese Funktionalität.

    Das Problem ist, die Funktion Schreibt nicht!!! Aber wieso? was ist falsch?

    Munich85 schrieb:

    Aber wieso? was ist falsch?
    Wie hast Du denn die Funktionen deklariert und die Parameter befüllt?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ThuCommix schrieb:

    Unten ist auch ein Beispiel, vielleicht hilft dir das.
    Hallo, dieser Link war natürlich auch teil meiner umfangreichen Google-Suche und ist auch teil des von mir erstellen Codes (der ja leider nicht geht)

    @RodFromGermany: Alle Deklarationen und Variablen sind im geposteten Code enthalten. Dieser sollte meiner Meinung nach genau so laufen können (was er leider nicht tut)

    Munich85 schrieb:

    Private Declare Function WriteFile Lib "kernel32" ( _ ByVal hFile As IntPtr, _ lpBuffer As IntPtr, _ ByVal nNumberOfBytesToWrite As Int32, _ lpNumberOfBytesWritten As Int32, _ ByVal lpOverlapped As IntPtr _ ) As Int32

    Munich85 schrieb:

    retVal = WriteFile(hDevice, mybytes(0), 512, nRead, ovlRead)


    Ich sage gleich, ich kenne mich da mit Syntax von VB nicht perfekt aus, aber könnte nicht da ein Problem sein? Du übergibst statt dem Zeiger auf den Buffer nur den ersten Wert (in C ist es so, da übergibt man die Adresse vom ersten Arrayelement, aber hier kannst du ja nicht sagen, dass du explizit die Adresse übergibst)?
    Zumindest fällt es mir auf, dass es eine Gemeinsamkeit zwischen WriteFile und ReadFile darstellt (die beide nicht gehen) und sich von CreateFile (das funktioniert) unterscheidet.

    Ich weiß aber nicht, wie man sonst IntPtr erzeugt, bei MSDN stand aber was von Konvertierung, vielleicht solltest du es ausprobieren.

    EDIT: Ich habe dazu das gefunden: msdn.microsoft.com/de-de/libra…s.marshal.readintptr.aspx

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „sonne75“ ()

    Hallo,


    das war wirklich das Problem. Ich habe nicht richtig mit Byref und ByVal gearbeitet.

    Jetzt bin ich schon einen erheblichen schritt weiter!

    leider Kann ich beim Schreiben auf "\\.\G:" nur Sektor 0 adressieren. da dies der Bootsektor ist ist nach dem Schreiben auf diesen Sektor dann leider auch Schluss.

    und wenn ich explizit in ein File schreibe "\\.\G:\file" ist nach 12 Sektoren also 12*512 als 6kb Schluss.


    aber ich habe wieder neue Motivation geschöpft, dies auch noch zu lösen!


    Danke!


    Grüße,


    Matthias


    Noch der vollständigkeit halber:


    Richtig ist: (das Byref hatte natürlich gefehlt) IntPtr muss sein, sonst gehts nicht!


    VB.NET-Quellcode

    1. Private Declare Function ReadFile Lib "kernel32" ( _ ByVal hFile As IntPtr, _ ByRef lpBuffer As IntPtr, _ ByVal nNumberOfBytesToRead As Int32, _ ByRef lpNumberOfBytesRead As Int32, _ ByVal lpOverlapped As IntPtr _ ) As Int32

    Wie hast du es denn mit IntPtr gelöst?

    Und wenn du wieder unterschiedliche Schreibweisen (wie im ersten Beitrag gepostet) ausprobierst? Damals sind sie ja wegen dem falschen Zeiger nicht gelaufen...

    EDIT: funktioniert es tatsächlich, wenn du nur ByRef reinschreibst und den ersten Arrayelement übergibst? Gut zu wissen.
    Hallo,

    also es wird zunächst mal überhaupt was geschrieben und die Funktion antwortet nicht mit 0 :) Das ist schon mal +100% und ein Zeichen, dass ich in der richtigen Richtung unterwegs bin.

    Ich kann noch nicht bestätigen, das ich das richtige schreibe aber das wird meine nächste Baustelle :)

    Grüße,

    Matthias