Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehleranfääliges DirectoryExists auch in Delphi > XE 1? (https://www.delphipraxis.net/182746-fehleranfaeaeliges-directoryexists-auch-delphi-xe-1-a.html)

CCRDude 14. Nov 2014 12:26

Delphi-Version: XE

Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Unter Delphi XE finde ich in der SysUtils.pas:

Delphi-Quellcode:
function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean;
var
  Code: Cardinal;
  Handle: THandle;
  LastError: Cardinal;
begin
  Result := False;
  Code := GetFileAttributes(PChar(Directory));

  if Code <> INVALID_FILE_ATTRIBUTES then
  begin
    [...]
  end
  else
  begin
    LastError := GetLastError;
    Result := (LastError <> ERROR_FILE_NOT_FOUND) and
      (LastError <> ERROR_PATH_NOT_FOUND) and
      (LastError <> ERROR_INVALID_NAME);
  end;
end;
Leider ist das fehleranfällig - es gibt Situationen, in denen GetLastError bei nicht existierenden Pfaden ungleich einer der drei Fehlermeldungen ist und damit die Existenz eines nicht existierenden Verzeichnisses angenommen wird. So erlebt unter Windows PE (Vista, Win7, Win 8 AIK/ADK-Versionen), allerdings nicht generell. Welcher Fehler dort gemeldet wird, habe ich noch nicht rausgefunden, da er nur bei Kunden auftritt, und ich ihn meist schon umschifft habe, indem ich Verzeichnisse mit FindFirst suche.

Generell ist es natürlich fehleranfällig, Erfolg anzunehmen, nur weil drei bestimmte Fehler nicht aufgetreten sind.

Daher meine Frage: ist dies in neueren Delphi-Versionen besser gelöst, kann da jemand mal in die SysUtils.pas / System.SysUtils.pas schauen bitte?
Kann das selber nicht nachschauen, die Trial hat scheinbar keine Sourcen dabei.

Bernhard Geyer 14. Nov 2014 12:56

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
In XE wird gegen folgende Fehlercodes geprüft:

ERROR_FILE_NOT_FOUND
ERROR_PATH_NOT_FOUND
ERROR_BAD_PATHNAME
ERROR_INVALID_NAME
ERROR_BAD_NETPATH
ERROR_NOT_READY
ERROR_BAD_NET_NAME

Sir Rufo 14. Nov 2014 13:57

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Mal anders gefragt:

In welchen Situationen kann es dazu kommen, dass
Delphi-Quellcode:
GetFileAttributes(PChar(Directory)) = INVALID_FILE_ATTRIBUTES
und es trotzdem um ein existierendes Verzeichnis handelt?

Ich hätte jetzt mal pauschal vermutet: keine.

Also könnte der Code wie folgt lauten
Delphi-Quellcode:
function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean;
var
  Code: Cardinal;
  Handle: THandle;
  LastError: Cardinal;
begin
  Result := False;
  Code := GetFileAttributes(PChar(Directory));

  if Code <> INVALID_FILE_ATTRIBUTES then
  begin
    [...]
  end
  else
  begin
    Result := False;
{
    LastError := GetLastError;
    Result := (LastError <> ERROR_FILE_NOT_FOUND) and
      (LastError <> ERROR_PATH_NOT_FOUND) and
      (LastError <> ERROR_INVALID_NAME);
}
  end;
end;
ansonsten sollten die den Rückgabewert ändern auf
Delphi-Quellcode:
TDirectoryExistsResult = ( True, False, KnownByVulture );
:mrgreen:

Uwe Raabe 14. Nov 2014 14:14

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1279829)
Mal anders gefragt:

In welchen Situationen kann es dazu kommen, dass
Delphi-Quellcode:
GetFileAttributes(PChar(Directory)) = INVALID_FILE_ATTRIBUTES
und es trotzdem um ein existierendes Verzeichnis handelt?

Ich hätte jetzt mal pauschal vermutet: keine.

Nicht ganz:

Zitat:

If you call GetFileAttributes for a network share, the function fails, and GetLastError returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.

Sir Rufo 14. Nov 2014 14:43

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1279833)
Zitat:

Zitat von Sir Rufo (Beitrag 1279829)
Mal anders gefragt:

In welchen Situationen kann es dazu kommen, dass
Delphi-Quellcode:
GetFileAttributes(PChar(Directory)) = INVALID_FILE_ATTRIBUTES
und es trotzdem um ein existierendes Verzeichnis handelt?

Ich hätte jetzt mal pauschal vermutet: keine.

Nicht ganz:

Zitat:

If you call GetFileAttributes for a network share, the function fails, and GetLastError returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.

Soso, und wenn dieser Fehler da ist, dann ist es trotzdem ein existierendes Verzeichnis und der Rückgabewert muss
Delphi-Quellcode:
true
sein?

Kann ich nicht so wirklich glauben, denn
Zitat:

Zitat von Bernhard Geyer (Beitrag 1279819)
In XE wird gegen folgende Fehlercodes geprüft:

ERROR_FILE_NOT_FOUND
ERROR_PATH_NOT_FOUND
ERROR_BAD_PATHNAME
ERROR_INVALID_NAME
ERROR_BAD_NETPATH
ERROR_NOT_READY
ERROR_BAD_NET_NAME

Aha, also ergibt das auch
Delphi-Quellcode:
false
...

Also bei welcher Gelegenheit muss
Delphi-Quellcode:
DirectoryExists
ein
Delphi-Quellcode:
true
zurückliefern trotz dass wir bei
Delphi-Quellcode:
GetFileAttributes(PChar(Directory))
aks Rückgabe ein
Delphi-Quellcode:
INVALID_FILE_ATTRIBUTES
bekommen?

pelzig 14. Nov 2014 15:18

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Mal ganz extrem dumm gefragt:

Wat gibbes rück?

Ist das letzte Zeichen des Rückgabewertes etwa ein Backslash?

MfG

Sir Rufo 14. Nov 2014 15:27

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Ok, die wirklich korrekte Umsetzung der Funktion müsste so lauten:
Delphi-Quellcode:
function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean;
var
  Code: Cardinal;
  Handle: THandle;
  LastError: Cardinal;
begin
  Result := False;
  Code := GetFileAttributes(PChar(Directory));

  if Code <> INVALID_FILE_ATTRIBUTES then
  begin
    [...]
  end
  else
  begin
    LastError := GetLastError;
    if
      (LastError <> ERROR_FILE_NOT_FOUND) and
      (LastError <> ERROR_PATH_NOT_FOUND) and
      (LastError <> ERROR_BAD_PATHNAME) and
      (LastError <> ERROR_INVALID_NAME) and
      (LastError <> ERROR_BAD_NETPATH) and
      (LastError <> ERROR_BAD_NET_NAME)
    then // Wir können keine Aussage darüber treffen, daher
      RaiseLastOSError( LastError );
  end;
end;
System Error Codes (0-499)

Bei einem
Delphi-Quellcode:
ERROR_TOO_MANY_OPEN_FILES
kann man einfach keine Aussage darüber treffen, ob das Verzeichnis existiert oder nicht. Also entweder einen TriState (Ja, Nein, WeissDerGeier) zurückliefern oder eine Exception werfen.

Sir Rufo 14. Nov 2014 15:30

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Zitat:

Zitat von pelzig (Beitrag 1279840)
Mal ganz extrem dumm gefragt:

Wat gibbes rück?

Ist das letzte Zeichen des Rückgabewertes etwa ein Backslash?

MfG

Ja mit einer hübschen Schleife drumherum :shock:

Rückgabewert von
Delphi-Quellcode:
DirectoryExists
BOOLEAN
Rückgabewert von
Delphi-Quellcode:
GetFileAttributes
Cardinal
Rückgabewert von
Delphi-Quellcode:
GetLastError
Cardinal

Da ist nicht viel Raum für ein Backslash

Uwe Raabe 14. Nov 2014 15:32

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1279839)
Soso, und wenn dieser Fehler da ist, dann ist es trotzdem ein existierendes Verzeichnis und der Rückgabewert muss
Delphi-Quellcode:
true
sein?

Ich meine schon. Schließlich existiert ja die Root des Share. Ob ich da reinschreiben kann ist wieder eine andere Frage.

Zitat:

Zitat von Sir Rufo (Beitrag 1279839)
Kann ich nicht so wirklich glauben, denn
...
Aha, also ergibt das auch
Delphi-Quellcode:
false

Ich habe ja nicht behauptet, daß die Implementation korrekt ist :-D

Sinnigerweise verhält sich Windows (zumindest 8.1) in diesem Punkt gar nicht nach der Dokumentation. Auch mit einem Network-Share kommt kein INVALID_FILE_ATTRIBUTES zurück, so daß dieses Argument wohl nicht zieht.

Aber vom Prinzip hat der OT schon Recht: es ist einfach ungeschickt, auf die möglichen Fehler abzuprüfen, anstatt auf die möglichen Ausnahmen von den Fehlern. Die Exception bei einem unerwarteten Rückgabewert gehört natürlich auch zum guten Standard.

Sir Rufo 14. Nov 2014 15:36

AW: Fehleranfääliges DirectoryExists auch in Delphi > XE 1?
 
Hier mal die Rückgabewerte und den entsprechenden LastError
DirectoryResultLastError
\\FalseERROR_INVALID_NAME
\\serverFalseERROR_BAD_PATHNAME
\\server\FalseERROR_BAD_PATHNAME
\\server\notexistingFalseERROR_BAD_PATHNAME
\\server\existingTrue 


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:58 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz