WIndows API Funktion LockFile

  • Hallo Leute!

    Kann mir jemand erklären wie ich API Funktionen in Autoit nutzen kann.
    Soweit ich jetzt im Internet gelesen habe sind das Funktione die in DLL´s vorhanden sind.
    Konkret geht es um http://msdn.microsoft.com/en-us/library/…28VS.85%29.aspx eine Datei zu sperren.

    [autoit]

    $file = FileOpen ( "filename", mode )
    DllCall("Kernel32.dll", "BOOLEAN", "LockFile", "hwnd", $file)

    [/autoit]


    Den Code habe ich mir nur irgendwie zusammen gesucht und wird auch so nicht stimmen.
    Deshalb auch meine Bitte um Hilfe.

    Ich möchte damit eine Datei während ein Script läuft vor Bearbeitung und Kopierversuchen zu schützen.
    Wenn das Script fertig ist soll ein UnlockFile Dllcall erfolgen um die Datei wieder freizugeben.

    lg
    Concara

    If not :?: then ?( else :thumbup:

    Einmal editiert, zuletzt von Concara (26. Januar 2010 um 09:17)

  • Hi,
    du kannst mit

    [autoit]

    _WinAPI_CreateFile()

    [/autoit]

    die Datei öffnen um sie exclusiv nur für dein script bearbeitbar zu machen.
    also z.B.

    [autoit]

    $hFile=_WinAPI_CreateFile("datei.dat",2 (datei öffnen), 2 (lesen erlauben) + 4 (schreiben erlauben))

    [/autoit]

    s. auch Beispiel in der Hilfe

  • Andy

    Super Danke das hilft mir weiter. Ah und in der Winapi.au3 sind auch die Dllcalls "versteckt".


    @ALL
    Kann mir wer das trotzdem mit Lockfile als Funktion, in einen Dllcall verwandel.
    Sprich mir ein Beispielscript zeigen.
    Denn das Aufrufen von Dlls ist für mich immer noch ein unbeschriebenes Blatt.

    Danke
    Concara

    If not :?: then ?( else :thumbup:

  • Spoiler anzeigen
    [autoit]


    $path = ""
    $file = FileOpen ( $path,0 )
    $call =DllCall("Kernel32.dll", "bool", "LockFile", "hwnd", $file, "int", "", "int","", "int", "", "int", "")
    ;die Parameter geben so natürlich recht wenig Sinn
    if @error then ConsoleWrite("error " &@error)
    if IsArray($call) then ConsoleWrite($call[0] & " " & $call[1])

    [/autoit]


    So müsste das gehen.

  • nuts
    funktioniert so nicht, da der in der dll benötigte Filehandle nicht der ist, den AutoIt zurückgibt!
    Beschreibung aus http://msdn.microsoft.com/en-us/library/aa365202(VS.85).aspx :

    Zitat

    The file handle must have been created with the GENERIC_READ or GENERIC_WRITE access right.

    Das heißt konkret, daß das Filehandle mit den anderen API-Funktionen (dll-Aufrufen) ermittelt werden muß. Habe hier zzt. nur Produktivmaschinen und

    Was ich nicht verstehe ist, was an

    [autoit]

    _WinAPI_CreateFile()

    [/autoit]

    so kompliziert ist. Im Beispiel in der Hilfe sind mehrere Anwendungen zum Schreiben/Lesen/Bearbeiten der Datei aufgeführt. Und ob man mit Fileread/Filewrite oder mit den dort beschriebene Methoden macht ist doch egal...

  • Naja ich konnte das nicht testen (leider kein Autoit hier), aber woher weisst du mit welcher API Fileopen arbeitet? ?(
    Sollte das handle wirklich nicht stimmen muss man weiter im msdn nach der richtigen API forschen :whistling:

    \edit Aha Fileopen verwendet vermutlich die Funktion Fileopen :rofl:

    Einmal editiert, zuletzt von nuts (22. Januar 2010 um 14:52)

  • Zitat

    Aha Fileopen verwendet vermutlich die Funktion Fileopen

    RISCHDIIIIISCH!^^
    Man sollte testen ob in der "neuen" AutoIt-Version das Lesen/Schreiben-Flag von FileOpen() nicht schon die Datei lockt! Beim Schreiben ist die Datei m.W. schon von Windows aus für den Zugriff gesperrt....

    Workaround:
    File locken, indem man sie mit fileopen($datei,1) öffnet. Datei "offen lassen"...
    Wenn man Daten lesen möchte, Datei schließen und mit fileopen($datei,0) die Daten lesen, anschließend sofort wieder locken....


    /EDIT/ so ganz ist der Alzheimer noch nicht fortgeschritten^^ Ich wußte doch, da war was...

    Zitat

    Changed: It is now possible to read from files opened for writing.

    aus der History 3.3.2.0
    Leider funktioniert das bei mir nicht, eine zum Schreiben geöffnete Datei verursacht beim Lesen einen Fehler...

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    3 Mal editiert, zuletzt von Andy (22. Januar 2010 um 15:42)

  • so gehts....

    [autoit]


    $file="datei.bat"

    [/autoit][autoit][/autoit][autoit]

    $hfile=fileopen($file,1) ;Datei zum SCHREIBEN öffnen (lock)
    Local $n = FileSetPos($hFile, 0, 0) ;pointer an den Anfang der Datei=0 oder an irgendeine Position innerhalb der datei

    [/autoit][autoit][/autoit][autoit]

    $data=fileread($hfile) ;daten ab dem pointer lesen
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $data = ' & $data & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit][autoit][/autoit][autoit]

    do
    until guigetmsg()=-3

    [/autoit][autoit][/autoit][autoit]

    fileclose($hfile)

    [/autoit]
  • Hi!

    Danke Andy und nuts !!!

    Mit _WinAPI_CreateFile() funktioniert das ganz gut. Andy es ist auch nicht kompliziert!
    Was ich wollte ist eigendlich DllCall und da sind mir die Parameter noch nicht ganz klar.
    Hat also mit der Verwendung von _WinAPI_CreateFile() nichts zu tun.

    Das Beispiel von nuts hat auch funktioniert.
    Wie gesagt da sind mir beim Dllcall diese int noch nicht verständlich.

    Zitat
    [autoit]

    $call =DllCall("Kernel32.dll", "bool", "LockFile", "hwnd", $file, "int", "", "int","", "int", "", "int", "")

    [/autoit]

    LG
    Concara

    If not :?: then ?( else :thumbup:

  • Hi,
    Lockfile ist NICHT dazu da, um allen Programmen den Zugriff auf die gelockte Datei zu verwehren!

    Folgendes Script als LockFile1.exe kompilieren und starten, es legt eine Datei "Test.dat" an, bei der Teile der Datei gelockt werden. Trotzdem kann man mit z.B. Notepad die Datei ganz normal lesend öffnen!

    Spoiler anzeigen
    [autoit]

    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_outfile=lockfile1.exe
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $file = "test.dat"
    $a = FileDelete($file)
    FileWriteLine($file, "Zeile1") ;8 Zeichen
    FileWriteLine($file, "Zeile2") ;8 Zeichen
    FileWriteLine($file, "Zeile3") ;8 Zeichen

    [/autoit] [autoit][/autoit] [autoit]

    $size = FileGetSize($file) ;dateigröße

    [/autoit] [autoit][/autoit] [autoit]

    $hfile = _WinAPI_CreateFile($file, 2, 2, 2) ;bestehende öffnen, lesen, share=lesen

    [/autoit] [autoit][/autoit] [autoit]

    $offset_low = 9 ;anfang lock
    $offset_high = 0
    $lenght_lock_low = 6 ;länge lock
    $lenght_lock_high = 0

    [/autoit] [autoit][/autoit] [autoit]

    $call = DllCall("Kernel32.dll", "bool", "LockFile", "hwnd", $hfile, "dword", $offset_low, "dword", $offset_high, "dword", $lenght_lock_low, "dword", $lenght_lock_high)
    If @error Or (Not IsArray($call)) Then
    MsgBox(0, 0, "Fehler beim Dateizugriff")
    Else
    If $call[0] <> 0 Then
    MsgBox(0, "Erfolg= " & $call[0], "Datei(bereich) erfolgreich gelockt, filehandle=" & $call[1])
    Else
    MsgBox(0, "Erfolg= " & $call[0], "Fehler beim Dateizugriff, filehandle=" & $call[1])
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Do
    Until GUIGetMsg() = -3

    [/autoit]

    Nun einfach die LockFile1.exe nochmal starten, man bekommt eine Fehlermeldung (bezüglich LOCK), aber gleichzeitig das richtige Filehandle!

    Nun folgendes Script starten um die gelockten Bereiche innerhalb der Datei anzuzeigen:

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $nbytes, $string = "",$file = "test.dat"

    [/autoit] [autoit][/autoit] [autoit]

    $hfile = _WinAPI_CreateFile($file, 2, 2, 2) ;bestehende Datei öffnen, lesen, share=lesen

    [/autoit] [autoit][/autoit] [autoit]

    $size = FileGetSize($file) ;dateigröße

    [/autoit] [autoit][/autoit] [autoit]

    $tBuffer = DllStructCreate("byte[1]") ;puffer für die zu lesenden Daten, hier zur einzelne Zeichen

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To $size-1 ;alle Zeichen in der Datei

    [/autoit] [autoit][/autoit] [autoit]

    _WinAPI_SetFilePointer($hfile, $i) ;Pointer auf Zeichen setzen
    $erfolg = _WinAPI_ReadFile($hfile, DllStructGetPtr($tBuffer), 1, $nbytes) ;Zeichen lesen

    [/autoit] [autoit][/autoit] [autoit]

    If $erfolg Then
    $sText = BinaryToString(DllStructGetData($tBuffer, 1)) ;Zeichen lesen
    Else
    $sText = "" ;kein Zeichen
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $string &= "Position: " & $i & " lock= " & Not ($erfolg) & " Zeichen=" & $sText & @CRLF ;Ausgabestring

    [/autoit] [autoit][/autoit] [autoit]

    Next
    MsgBox(0, "Anzeige gelockter Zeichen", $string)

    [/autoit] [autoit][/autoit] [autoit]

    _WinAPI_CloseHandle($hfile)

    [/autoit]

    Man sieht, daß die gelockten Zeichen nicht zu lesen sind!

    Nun im Script Lockfile1 die folgenden Zeilen austauschen und als Lockfile2.exe kompilieren und starten.

    [autoit]

    $offset_low = 2 ;anfang lock
    $offset_high = 0
    $lenght_lock_low = 3 ;länge lock
    $lenght_lock_high = 0

    [/autoit]


    In der Test.dat werden nun ZUSÄTZLICH die Zeichen von 2-5 gelockt. Das kann man mit Anzeigescript feststellen. Trotzdem kann Notepad alle Zeilen lesen!

    LockFile bringt also nur etwas, um z.B. bei einer Datenbankanwendung den Lesezugriff der Clients zu sperren, wenn in der offenen Datenbank Schreibzugriffe stattfinden.

    Um die Test.dat auch wieder zu entlocken sollten nun genug Informationen da sein. ;)

  • Hi Andy !

    Vielendank für diese sehr umfangreiche Erklärung!!!

    Mein ürsprünglicher wunsch war es die Datei komplett zu sperren, sprich weder lesen noch schreiben.
    Das geht ja mit dem Befehl _WinAPI_CreateFile den du mir genannt hast.

    Kann mann mit $offset_high und $lenght_lock_high einen zweiten Bereich innerhalb der Datei locken?

    LG
    Concara

    If not :?: then ?( else :thumbup: