Einzelnen Beitrag anzeigen

Benmik

Registriert seit: 11. Apr 2009
560 Beiträge
 
Delphi 12 Athens
 
#9

AW: FindFirstFileNameW aufrufen

  Alt 12. Jan 2014, 17:26
Vielen Dank für deine Mühe, besonders dafür, dass du den Code auch noch didaktisch entwickelt hast, und das um 1:18 Uhr nachts. Auch wenn man förmlich die Watschen hört, gefolgt von einem "Sechs! Setzen!". Aber ich weiß genau, dass hier viele mitlesen, die mit denselben Problemen kämpfen und froh sind über jede Aufklärung.
Natürlich war der Code auch nicht sozusagen als fertige Lösung gedacht, er war lediglich als Machbarkeitsstudie intendiert, weil er überhaupt im Prinzip funktionierte.

Ein kleiner Trost ist es, dass der Code vom Meister auch nicht so ohne weiteres läuft.
Bei Handle := FindFirstFileNameW(PWideChar(Dateiname),0,@PDatLänge,@PLinkName); moniert der Compiler, dass die Parameter formal nicht stimmen, genauso wie bei LinkName : array[0..MAX_PATH] of WideChar; .

Daher mein nächster Versuch:
Delphi-Quellcode:
procedure TForm1.ZeigeHardlinks;
var
  Dateiname : WideString;
  PLinkLänge : PDWord;
  PLinkName : PWideChar;
  Handle : Cardinal;
begin
  Dateiname := 'C:\Temp\Hardlink.JPG';
  PLinkName := GetMemory(MAX_PATH * 2 + 2); // +2 für die abschließende #0
  PLinkLänge := GetMemory(SizeOf(PDWord));
  //PLinkLänge^ := MAX_PATH;
  Try
    Handle := FindFirstFileNameW(PWideChar(Dateiname), 0, PLinkLänge, PLinkName);
    If GetLastError = ERROR_MORE_DATA then begin
      Showmessage(SysErrorMessage(GetLastError));
    end else if Handle = INVALID_HANDLE_VALUE then begin
      RaiseLastOSError;
    end else begin
      Repeat
        ShowMessage(PWideChar(@PLinkName));
        //PLinkLänge^ := MAX_PATH;
      Until not FindNextFileNameW(Handle, PLinkLänge, PLinkName);
    end;
  Finally
    FreeMemory(PLinkName);
    FreeMemory(PLinkLänge);
    FileClose(Handle);
  End;
end;
Dieser Code funktioniert in dem Sinn, dass die Namen richtig ausgegeben werden. Bei FreeMemory(PLinkName); knallt es aber. Schleierhaft, wieso.

Die Zuweisung PLinkLänge^ := MAX_PATH; funktioniert, ist aber unnötig, denn - wie du ja auch ausführst - wird die Variable nur gebraucht, sollte der Puffer von PLinkName zu klein für den Linknamen, sie enthält dann den Wert für die notwendige Größe. Merkwürdig ist nur, dass es bei einer erneuten Zuweisung nach ShowMessage(PWideChar(@PLinkName)); knallt. Im Debugger sieht man, dass der Wert von PLinkLänge^ nach Aufruf von FindFirstFileNameW plötzlich nicht mehr verfügbar ist. Und leider ebenfalls unverständlich ist mir, dass die Sache mit ERROR_MORE_DATA nicht funktioniert, wenn ich den Puffer von PLinkName absichtlich zu klein bemesse (z.B. PLinkName := GetMemory(2); , obwohl das nicht sein dürfte und bei meinen früheren Versuchen auch korrekt ERROR_MORE_DATA zurückgegeben wurde. Klappen tut die Sache trotzdem! Und was passiert da nun?

Noch eine kleine Bemerkung zu "4294967295" statt INVALID_HANDLE_VALUE. Im Entwurfsmodus hat INVALID_HANDLE_VALUE den Wert -1, wird aber dennoch treuherzig als "Cardinal" deklariert. Zur Laufzeit wechselt der Wert im Debugger dann zu den besagten 4294967295, was schon sehr irritierend ist. Ein Ausflug in die Welt von DWORD bei Windows erklärt dann so einiges. Bei mir hat der Compiler in einigen Fällen (nicht in allen ?!) darauf hingewiesen, dass If Handle = INVALID_HANDLE_VALUE immer "Falsch" ergibt - logisch bei Cardinal und einem Wert von -1 zur Entwufszeit.

Für weitere Erhellung des Codes oben wäre ich dankbar.

Geändert von Benmik (12. Jan 2014 um 17:56 Uhr) Grund: Sprachliche Glättung
  Mit Zitat antworten Zitat