Frage zu FindFileFirst

  • Hallo !
    Ich habe ein kleines Problem mit der "FindFileFirst()"-Funktion.

    In der Hilfe dazu steht ja u.a.:
    Rückgabewert

    Fehler: Gibt -1 zurück, wenn ein Fehler aufgetreten ist. Wenn der Ordner leer ist, wird @error auf 1 gesetzt.

    Stimmt das eigentlich ?
    Wenn der angegebene Ordner leer ist gibt diese Funktion immer nur -1 zurück, aber @error wird nie gesetzt.


    Da scheint wohl irgendetwas nicht so ganz zu stimmen.
    Bevor ich da aber etwas in der Hilfe ändere wollte ich aber lieber mal nachfragen ob andere auch dieses Problem haben.

    MfG:
    BigRox

    P.S. Als Code zum testen verwende ich das Beispiel aus der deutschen Hilfe, nur schreibe ich darin anstelle von "If $search = -1 Then" "If @error Then"

    Einmal editiert, zuletzt von BigRox (22. Oktober 2011 um 18:16)

  • Wenn -1 zurückgegeben wird und nicht @error gesetzt wird heißt das eigentlich das der Ordner nicht existiert.
    Du fragst den @error-Wert auch wirklich direkt nach dem Funktionsaufruf ab?
    Und der zu prüfende Ordner existiert auch ganz sicher?

    Versuch mal ob du mit diesem Skript der Lösung näher kommst:

    Spoiler anzeigen
    [autoit]

    Global Const $s_Path = "C:\Deinpfad"

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

    Global $h_FFFF = FileFindFirstFile($s_Path & "\*")
    MsgBox(0,"", "übergebener Pfadstring: " & $s_Path & "\*" & @CRLF & "$h_FFFF: " & $h_FFFF & @CRLF & "@Error: " & @error)

    [/autoit]
  • Hallo AsperinJunkie !
    Zuerst in meinem ersten Post habe ich den Funktionsnamen versehentlich falsch geschrieben, es musste natürlich "FileFindFirstFile" heißen.

    Ich habe das Problem eben nochmal mit diesen beiden Scripts ausprobiert.
    Den benötigten Ordner habe ich vorher manuell angelegt.
    Dieses Script funktioniert richtig.

    Spoiler anzeigen


    $search = FileFindFirstFile("C:\Test\*.*")
    ; Prüfen, ob die Suche erfolgreich war
    If @error Then
    MsgBox(0, "Fehler", "Es wurden keine Dateien/Verzeichnisse gefunden, die zu dem Suchmuster passen")
    Exit
    EndIf
    ; weitere unwichtige Befehle...
    ; Handle für Suche schliessen
    FileClose($search)

    Und diese Version funktioniert nicht:

    Spoiler anzeigen


    $search = FileFindFirstFile("C:\Test\dfsetup207.exe")
    ; Prüfen, ob die Suche erfolgreich war
    If @error Then
    MsgBox(0, "Fehler", "Es wurden keine Dateien/Verzeichnisse gefunden, die zu dem Suchmuster passen")
    Exit
    EndIf
    ; weitere unwichtige Befehle...
    ; Handle für Suche schliessen
    FileClose($search)

    Der Unterschied ist, bei der zweiten Version habe ich keine Wildcards angegeben sondern einen Dateinamen (dfsetup207.exe) der aber nicht im Ordner (C:\Test) existiert.
    Somit müsste dann auch die Fehlermeldung erscheinen, da ja dann auch keine Datei dem Suchmuster entspricht.
    (wenn man sogar eine andere Datei in den Ordner kopiert, die nicht dem Suchmuster entspricht, erscheint auch keine Fehlermeldung (die Fehlermeldung erscheint anscheinend nur bei dem "*.*"-Suchmuster)).
    Tut es aber nicht, dann gibt die Funktion nur -1 zurück, obwohl der Ordner ganz sicher auch existiert.
    Da ist die Hilfe aber wohl nicht sehr hilfreich (verwendete Hilfeversion die aktuelle Onlinehilfe).

    MfG:
    BigRox

  • Hallo AsperinJunkie !
    Zum erklären warum ich die FileFind…-Funktionen überhaupt ausprobiert habe.

    Ich habe mir ein Installationsscript für das Programm „Defraggler“ geschrieben.
    Das Script funktioniert auch gut, nur wenn sich die Programmversion von Defraggler ändert muss ich auch das Script entsprechend ändern, da der Namen der exe-Datei auch die Versionsnummer enthält (die 207 im Namen).

    Nun probiere ich schon seit einiger Zeit diese „etwas unschöne“ Sache durch den Einsatz eines regulären Ausdrucks im „Run“-Befehl zu ändern.
    (So ähnlich wie bei dem Fenstertitel mit „RegExpTitel()“).
    Da mir dies aber bis heute nicht gelungen ist, habe ich es einmal mit den FindFile…-Funktionen ausprobiert.
    (Mit Hilfe von Wildcards ( Run($Pfad_Install_Programm & "\ dfsetup*.exe“...) ) geht das anscheinend auch nicht).
    Ich muss ja nach einem Dateinamen mit Wildcard suchen (dfsetup*.exe) und dann von der Funktion den richtigen Dateinamen (dfsetup207.exe) zurückgegeben bekommen um diesen dann im Run-Befehl zu verwenden.

    Mit den FindFile…-Funktionen funktioniert das auch ganz gut, nur wenn da gar keine Setupdatei in dem Ordner ist, müsste eigentlich eine Fehlermeldung erscheinen wenn man @error abfragt. In diesem Fall muss man aber den Rückgabewert auf den Wert -1 testen.

    Hier einmal ein erster Script-Entwurf:

    Spoiler anzeigen


    ; Einigen Variablen Werte zuweisen.
    $Install_Pfad = @ProgramFilesDir & "\Sonstige\Defraggler"
    $Pfad_Install_Programm = @HomeDrive & "\Defraggler\Programm"

    $Such_Handle = FileFindFirstFile($Pfad_Install_Programm & "\dfsetup*.exe")
    If @error Or $Such_Handle = -1 Then
    MsgBox(262192, "! ! ! F E H L E R ! ! !", 'Beim ausführen der "FindFileFirst()"-Funktion ist ein Fehler aufgetreten !')
    EndIf

    $Datei = FileFindNextFile($Such_Handle)
    FileClose($Such_Handle)

    ; Das Installationsprogramm von "Defraggler", mit Silent Schalter, aufrufen.
    Run($Pfad_Install_Programm & "\" & $Datei & " /D=" & $Install_Pfad)

    ; Funktion zum warten auf das erste Fenster aufrufen.
    $Fenster_Text = "Deutsch" ; Der Text gilt auch für das folgende Fenster 1.

    ; massenweise Befehle bis Exit


    Das Script sieht zwar noch ziemlich chaotisch aus aber es funktioniert schon mal.
    Aber es funktioniert nur mit der Zeile:
    "If @error Or $Such_Handle = -1 Then"
    richtig.
    Nur mit "If @error Then" funktioniert es nicht wenn der Ordner keine dem Suchmuster entsprechenden Dateien enthält (aber existiert).


    MfG:
    BigRox

  • Ich habe mal einen leeren Ordner "C:\Test" erstellt und darin eine Datei dfsetup207.exe erstellt.
    Dann folgendes Skript laufen lassen:

    Spoiler anzeigen
    [autoit]

    Global Const $s_Path = "C:\Test\"
    Global Const $s_Pattern = "dfsetup207.exe" ; alternativ: "dfsetup*.exe"

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

    Global $s_File, $h_FFFF = FileFindFirstFile($s_Path & $s_Pattern)

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

    MsgBox(0,"", "übergebener Pfadstring: " & $s_Path & $s_Pattern & @CRLF & "$h_FFFF: " & $h_FFFF & @CRLF & "@Error: " & @error)

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

    If $h_FFFF <> -1 Then
    Do
    $s_File = FileFindNextFile($h_FFFF)
    If @error Then ExitLoop
    MsgBox(0,"gefundene Datei", $s_File)
    Until 0
    EndIf

    [/autoit]


    Egal ob direkt den Namen eingetragen oder mit WildCard: $h_FFFF ist korrekterweise ungleich -1 (das Minus beachten!) und @error ist ebenso korrekterweise 0.
    Bei beiden wird mir beim anschließenden FileFindNextFile() die korrekte Datei ausgegeben.
    Wenn ich die Datei entferne (und der Quellordner damit leer ist) wird $h_FFFF = -1 und @error bleibt 0.
    Ich kann dein Problem also nachvollziehen und es scheint sich um einen Bug zu handeln.
    Um wirklich zu wissen ob ein Ordner existiert nimm daher stattdessen FileExists() und ob er leer ist mit DirGetSize() in Verbindung mit dem Flag 1.

    P.S: Wenn du AutoIt-Code postest bitte in Zukunft nicht die Code-Tags sondern die speziell dafür vorgesehenen AutoIt-Tags nutzen - ist übersichtlicher.

  • Hi,

    anstatt @error abzufragen, kannst Du auch WinAPI_GetLastError aufrufen.

    Zitat von FindFirstFile

    Return value

    If the function succeeds, the return value is a search handle used in a subsequent call to FindNextFile or FindClose, and the lpFindFileData parameter contains information about the first file or directory found.

    If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE and the contents of lpFindFileData are indeterminate. To get extended error information, call the GetLastError function.

    If the function fails because no matching files can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND.

    Spoiler anzeigen
    [autoit]


    Global Const $ERROR_FILE_NOT_FOUND = 2

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

    $search = FileFindFirstFile("C:\Test\dfsetup207.exe")
    ; Prüfen, ob die Suche erfolgreich war
    If (_WinAPI_GetLastError ( ) == 2) Then
    MsgBox(0, "Fehler", "Es wurden keine Dateien/Verzeichnisse gefunden, die zu dem Suchmuster passen")
    Exit
    EndIf
    ; weitere unwichtige Befehle...
    ; Handle für Suche schliessen
    FileClose($search)

    [/autoit]


    Gruß
    Greenhorn