Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Existenz langer Pfade (https://www.delphipraxis.net/193192-existenz-langer-pfade.html)

tomkupitz 3. Jul 2017 19:50

Existenz langer Pfade
 
Hallo,

ich prüfe ob ein langer Pfad existiert mit:

Code:
function DirExists(const Dirname: string): Boolean;
var FindData: TWin32FindData;
    Handle: THandle;

begin
  Handle:=FindFirstFileW(PWideChar('\\?\'+Dirname+#0#0), FindData);

  if Handle<>INVALID_HANDLE_VALUE then
  begin
    Windows.FindClose(Handle);

    result:=FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0;
  end
  else
    result:=False;
end;
Wenn Dirname ein Netzwerkpfad ist \\QNAP\abc ist funktioniert das nicht. Warum?

Beste Grüße

SneakyBagels 3. Jul 2017 20:20

AW: Existenz langer Pfade
 
Ich kann das jetzt nicht testen und will mir ehrlich gesagt keinen Pfad >255 auf einem Netzlaufwerk anlegen.

-- das hier ist offensichtlich falsch, also weg damit --
Aber lasse die ersten zwei \\ deines Netzwerkpfades mal weg. Denn \\?\QNAP\ ist glaube ich zulässig, nicht aber \\?\\\QNAP\.

Der schöne Günther 3. Jul 2017 20:32

AW: Existenz langer Pfade
 
Ich verstehe nicht - Willst du überprüfen ob es ein "langer Pfad" ist, also länger ist als die Windows-Konstante "MAX_PATH"? Oder willst du wissen ob der Pfad in UNC-Notation (\\host\path) ist?

Für letzteren Fall: Nimm einfach TPath.IsUncPath()

Die Antwort auf dein "Warum funktioniert das nicht?" ist dass du explizit nach lokal fragst.
https://de.wikipedia.org/wiki/Uniform_Naming_Convention

p80286 3. Jul 2017 21:05

AW: Existenz langer Pfade
 
https://de.wikipedia.org/wiki/Uniform_Naming_Convention

Da steht eigentlich alles drin. Für die wikipedia-Hasser "\\?\" bezeichnet ein lokales Laufwerk. auch wenn man einen servernamen hinten dran hängt bleibt es lokal, da wird nichts draus.

Gruß
K-H

Ok vergiss es ich bin einen Hundespaziergang zu spät:oops:

SneakyBagels 3. Jul 2017 21:23

AW: Existenz langer Pfade
 
Ich schicke meine Pfade immer alle durch die erste Funktion. Bisher lief immer alles glatt. Vielleicht hilft das ja
Delphi-Quellcode:
function getUNCPath(aPath: string): string;
begin
 if not Winapi.ShLwApi.PathIsNetworkPath(PWideChar(aPath)) then
  if not System.IOUtils.TPath.IsUNCPath(aPath) then
   aPath := '\\?\' + aPath;

 Result := aPath;
end;

function removeUNCFromPath(aPath: string): string;
begin
 if not Winapi.ShLwApi.PathIsNetworkPath(PWideChar(aPath)) then
  if System.IOUtils.TPath.IsUNCPath(aPath) then
   Delete(aPath, 1, 4);

 Result := aPath;
end;

// Test
 ShowMessage( getUNCPath('Y:\') ); // Y = Netzlaufwerk. Resultat => Y:\
 ShowMessage( getUNCPath('C:\') ); // C = Systemlaufwerk. Resultat => \\?\C:\

tomkupitz 3. Jul 2017 21:40

AW: Existenz langer Pfade
 
Danke für die Hinweise.

Es geht um eine kleine Backupfunktion die Ordner in einen Zielordner kopiert. Quell- oder Zielordner können im Netzwerk liegen.
Nun kam es vor, dass einige Pfade in den Quellordnern größer als MAX_PATH wurden oder gar Dateinamen Überlänge hatten. D.h. es kam folglich dazu, dass Quell- und Zielordner nicht gleich waren. Kurz: Welche Möglichkeit habe ich ausser "\\?\" Dateien mit langen Pfaden oder Dateinamenüberlänge mit CopyFile zu kopieren?

Beste Grüße

SneakyBagels 3. Jul 2017 21:51

AW: Existenz langer Pfade
 
Ich stand mal vor demselben Problem wie du.
Kurz: außer \\?\ wird dir nicht viel übrig bleiben. Wenn es was anderes gibt, kenne ich es nicht.

Nutze einfach meine Funktion getUNCPath. Die macht aus allen Pfaden UNC-Pfade und wenn dein Pfad ein Netzwerkpfad ist, macht die Funktion nichts.

Dalai 4. Jul 2017 00:59

AW: Existenz langer Pfade
 
Es gibt noch ein anderes Prefix "\??\", das für Reparse Points verwendet wird. Leider habe ich mangels Verständnis des Themenkomplexes keine Ahnung, ob das vielleicht auch für UNC funktioniert. Vielleicht einen Versuch wert?

Grüße
Dalai

samso 4. Jul 2017 11:40

AW: Existenz langer Pfade
 
Also laut dieser Doku https://msdn.microsoft.com/en-us/lib...).aspx#maxpath sollte es möglich sein, das wie folgt zu schreiben:

Code:
\\?\UNC\QNAP\abc

SneakyBagels 4. Jul 2017 11:53

AW: Existenz langer Pfade
 
Siehe:

Zitat:

Zitat von Der schöne Günther (Beitrag 1375880)
Ich verstehe nicht - Willst du überprüfen ob es ein "langer Pfad" ist, also länger ist als die Windows-Konstante "MAX_PATH"? Oder willst du wissen ob der Pfad in UNC-Notation (\\host\path) ist?

Für letzteren Fall: Nimm einfach TPath.IsUncPath()

Die Antwort auf dein "Warum funktioniert das nicht?" ist dass du explizit nach lokal fragst.
https://de.wikipedia.org/wiki/Uniform_Naming_Convention


samso 4. Jul 2017 13:33

AW: Existenz langer Pfade
 
Je nachdem ob es sich um einen UNC-Pfad handelt, oder um ein lokales Laufwerk muss man für lange Pfade unterschiedliche Präfixes anfügen. Mein erster Versuch daraus eine Funktion zu machen:

Delphi-Quellcode:
function GetPrefixedPath(const aPath: string): string;
begin
  if aPath.StartsWith('\\')
  then begin
    if System.IOUtils.TPath.GetExtendedPrefix(aPath)=TPathPrefixType.pptNoPrefix
    then
      Result := '\\?\UNC\' + copy(aPath, 3, MaxInt)
    else
      Result := aPath;
  end
  else
    Result := '\\?\' + aPath;

SneakyBagels 4. Jul 2017 13:48

AW: Existenz langer Pfade
 
Diese Funktion verstehe ich nicht ganz.
Könntest du ein paar Beispiele (Text, hier im Forum) anfügen?

So wie ich zuvor vielleicht
Delphi-Quellcode:
 ShowMessage( getUNCPath('Y:\') ); // Y = Netzlaufwerk. Resultat => Y:\
 ShowMessage( getUNCPath('C:\') ); // C = Systemlaufwerk. Resultat => \\?\C:\
Wo wir schon einmal dabei sind:
\\?\ lässt sich auch auf Netzlaufwerke anwenden, wenn sie gemounted sind (also keine reine IP).

Ich würde wenn dann ja eher so machen
Delphi-Quellcode:
function getUNCPath(const aPath: string): string;
begin
 Result := aPath;

 if not aPath.StartsWith('\\') then // <=== hinzugefügt, damit aus \\192.168.0.1 nicht \\?\\\192.168.0.1 gemacht wird
  if TPath.GetExtendedPrefix(aPath) = TPathPrefixType.pptNoPrefix then
   Result:= '\\?\' + aPath;
end;

function removeUNCFromPath(const aPath: string): string;
begin
 Result := aPath;

 if TPath.GetExtendedPrefix(aPath) = TPathPrefixType.pptExtended then // \\?\ present
  Delete(Result, 1, 4);
end;
Aber was ist jetzt richtig-er bzw überhaupt richtig und funktionstüchtig? Würde mich auch brennend interessieren.

samso 4. Jul 2017 14:37

AW: Existenz langer Pfade
 
Der Präfix \\?\ darf immer angefügt werden, weil das der Windows-Api lediglich mitteilt "Achtung der Pfad kann länger als MAX_PATH Zeichen sein"

"C:\EinPfad\usw.txt" => "\\?\C:\EinPfad\usw.txt"
"Y:\EinPfad\usw.txt" => "\\?\Y:\EinPfad\usw.txt"
"COM45:" => "\\?\COM45:"
"\\QNAP\MyShare\Daten\usw.txt" => "\\?\UNC\QNAP\MyShare\Daten\usw.txt"

SneakyBagels 4. Jul 2017 14:45

AW: Existenz langer Pfade
 
Zitat:

"\\QNAP\MyShare\Daten\usw.txt" => "\\?\UNC\QNAP\MyShare\Daten\usw.txt"
Wenn du deiner Funktion \\192.168.0.1\volumenname übergibst, dann würde \\?\UNC\192.168.0.1\volumenname daraus werden was in einem Fehler resultiert.

samso 4. Jul 2017 14:49

AW: Existenz langer Pfade
 
Zitat:

Zitat von SneakyBagels (Beitrag 1375960)
Wenn du deiner Funktion \\192.168.0.1\volumenname übergibst, dann würde \\?\UNC\192.168.0.1\volumenname daraus werden was in einem Fehler resultiert.

Habe ich bei mir gerade mit Windows 10 getestet. Ergibt bei mir keinen Fehler.

SneakyBagels 4. Jul 2017 14:51

AW: Existenz langer Pfade
 
Ist \\?\UNC\192.168.0.1\volumenname (oder welche IP auch immer, aber es muss eine IP sein) bei dir erreichbar mit \\?\UNC\ davor?

Edit:
gerade "\\?\UNC\192.168.0.1\volumenname" (Festplatte am Router die so auch zum Test existiert) unter Windows 10 getestet mit Resultat
Zitat:

[Window Title]
Explorer

[Content]
Die Datei "\\?\UNC\192.168.0.1\volumenname" wurde nicht gefunden. Überprüfen Sie die Schreibweise, und wiederholen Sie den Vorgang.

[OK]

samso 4. Jul 2017 14:58

AW: Existenz langer Pfade
 
Äh, Du testest das mit dem Windows-Explorer??

Nur noch mal zur Erläuterung: Ein UNC-Pfad hat die Form "\\server\blub". Der Präfix "\\?\" und "\\?\UNC\" hat mit UNC nichts zu tun, sondern ist eine Krücke die von MS irgendwann (für Windows NT?) erfunden wurde, um die API-Aufrufe zu erweitern.

Ich teste das z.B. mit
Delphi-Quellcode:
   
  if DirectoryExists(GetPrefixedPath('\\192.168.0.1\data\test'))
  then
    writeln('Direktory gefunden');
Und das funktioniert.

SneakyBagels 4. Jul 2017 15:12

AW: Existenz langer Pfade
 
Welchen Unterschied hat denn dann \\?\UNC und \\?\

?

samso 4. Jul 2017 15:37

AW: Existenz langer Pfade
 
Ich würde das mal frei so beschreiben:

"\\?\": Notation für ein lokales Laufwerke oder Gerät
"\\?\UNC\": Notation für ein Netzwerklaufwerk

Wie wir ja aus #1 gelernt haben funktioniert die Notation "\\?\\\QNAP\abc" ja nicht. Die Notation "\\?\UNC\QNAP\abc" führt hingegen zum gewünschten Ergebnis.

SneakyBagels 4. Jul 2017 15:53

AW: Existenz langer Pfade
 
Zitat:

"\\?\": Notation für ein lokales Laufwerke oder Gerät
"\\?\UNC\": Notation für ein Netzwerklaufwerk
So etwas in der Art dachte ich mir schon. Gut zu wissen. Ich denke unsere Lösungen sind jetzt quasi gleich. Aber ich bin sicher es geht noch besser.

Delphi-Quellcode:
function getUNCPath(const aPath: string): string;
begin
 Result := aPath;

 if aPath.StartsWith('\\') then
  begin
   if TPath.GetExtendedPrefix(aPath) = TPathPrefixType.pptNoPrefix then
    Result := '\\?\UNC\' + Copy(aPath, 3, Length(aPath));
  end
 else
  Result := '\\?\' + aPath;
end;

function removeUNCFromPath(const aPath: string): string;
begin
 Result := aPath;

 if TPath.GetExtendedPrefix(aPath) = TPathPrefixType.pptExtended then // \\?\ present
  Delete(Result, 1, 4)
 else if TPath.GetExtendedPrefix(aPath) = TPathPrefixType.pptExtendedUNC then // \\?\UNC\ present
  Delete(Result, 3, 6);
end;

p80286 4. Jul 2017 17:28

AW: Existenz langer Pfade
 
Also ich hab es gerade mal ausprobiert:
dir \\server\blub1\blub2\blub3 funktioniert
nach net use k: \\server\blub1\blub2
dir k:\blub3 funktioniert
dir \\?\k:\blub3 funktioniert
dir \\.\k:\blub3 funktioniert

also bezeichnet \\.\ bzw. \\?\ nicht ein phys. lokales sondern ein log. lokales Laufwerk.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:55 Uhr.

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