![]() |
Extrem langen Pfad kürzen, Result leer?
Wie würde man korrekt einen zu langen Pfad kürzen?
Ich habe eine Teststruktur die so aussieht:
Code:
Dieser Pfad ist so lang, dass ich das Verzeichnis 0123456789 selbst nicht mehr mit Windows kopiert bekomme.
D:\0123456789\11111111111111111111111111111111111111111111111111\22222222222222222222222222222222222222222222222222\
33333333333333333333333333333333333333333333333333\44444444444444444444444444444444444444444444444444\ 55555555555555555555555555555555555555555555555555\datei.txt Ist hier Schluss mit lustig und Hopfen und Malz verloren oder kann man hier noch was machen um die Datei zu kopieren? Das Kürzen mit dieser Funktion liefert einen leeren String zurück
Delphi-Quellcode:
function GetShortName(sLongName: string): string;
var sShortName: string; nShortNameLen: Integer; begin SetLength(sShortName, MAX_PATH); nShortNameLen := GetShortPathName(PChar(sLongName), PChar(sShortName), MAX_PATH - 1); if (0 = nShortNameLen) then begin // handle errors... end; SetLength(sShortName, nShortNameLen); Result := sShortName; end; |
AW: Extrem langen Pfad kürzen, Result leer?
Delphi müsste eigentlich ExtractShortPathName kennen (SysUtils).
Delphi-Quellcode:
sollte "C:\Progra~1\MyComp~1\MyApp\MyApp.exe" liefern.
ExtractShortPathName('C:\Program Files\MyCompany\MyApp\MyApp.exe')
Aus deinem Beispiel könnte damit dann sowas werden: D:\012345~1\111111~1\222222~1\333333~1\444444~1\55 5555~1\datei.txt |
AW: Extrem langen Pfad kürzen, Result leer?
Der Pfad ist mit 278 Zeichen länger als MAX_PATH. Die allermeisten der API-Funktionen dürften damit ihre Probleme haben. Lösung: Syntax benutzen, die längere Pfade erlaubt:
Code:
IIRC wird aber diese Syntax nicht von allen API-Funktionen unterstützt.
\\?\D:\0123456789\...
Grüße Dalai |
AW: Extrem langen Pfad kürzen, Result leer?
Keine Ahnung ob das relevant für Win7 ist. (Falls du es benutzt)
Check mal in der Registry ob 8dot3NameCreation aktiviert bzw. deaktiviert ist. ![]() gruss |
AW: Extrem langen Pfad kürzen, Result leer?
1) Ist aktiviert.
2) \\?\ hat kein Auswirkung auf Pfade > MAX_PATH 3) ExtractShortPathName ebenfalls ein leerer String So wie es aussieht, gibt es hier keine Lösung. Denn Windows selber kann das Verzeichnis sogar nicht verarbeiten. Frage: gilt MAX_PATH nur für Dateinamen oder für den kompletten Pfad? |
AW: Extrem langen Pfad kürzen, Result leer?
Ich hatte neulich mit einem Backup Probleme wegen zu langer Pfade.
Es gibt dafür naheliegende und absurde Lösungen/Vorschläge. Eine Möglichkeit, die bei mir prima funktioniert hat ist die Nutzung/ Erzeugung eines Links. (So wie man sie von Unixen kennt, ich glaub MS nennt das junction) per CMD: - Link auf irgendeinen mittleren Teil des Pfades anlegen - Löschen / Ändern im Link übrig bleibenden Pfadnamen - Link löschen Das kann man iterativ machen, bis ein "normaler" Zugriff funktioniert. Wahrscheinlich sogar intelligenter, wenn man ein bisschen Längenbestimmung macht. Es ist allerdings nicht in jeder OS Version verfügbar, bis XP glaub ich, erst ab Win7, bin nicht ganz sicher. Ggf. kannst Du das programmatisch implementieren, wenn Du mit der OS Version auf der sicheren Seite bist. |
AW: Extrem langen Pfad kürzen, Result leer?
MAX_PATH ist der komplette "Pfad", inkl. Datei-/Verteichnisname, Verzeichnisse, Laufwerk und der letzten #0.
|
AW: Extrem langen Pfad kürzen, Result leer?
Kann man dementsprechend abschließend festhalten, dass wenn die Länge Pfad sPathXYZ > MAX_PATH ist, man ihn am besten aus der Verarbeitung raushält um Fehler zu vermeiden?
|
AW: Extrem langen Pfad kürzen, Result leer?
Also direkt über die Win API kann man bis Windows 8.1 nur Pfade mit der Länge von MAX_PATH kopieren. Es gab aber die bereits erwähnte Alternative mit \\?\ um Pfade zu kopieren die länger sind als MAX_PATH. Probiert habe ich das selbst nie und kann daher auch keine Lösung anbieten. Ab Windows 10 (ab einem speziellen Build soweit ich weiß) wurden die WinAPI Funktionen angepasst sodass sie Pfade bis 2^15 Zeichen verarbeiten können.
|
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
Probiert habe ich es selbst auch nie, aber da ich weiß, dass Total Commander mit Pfaden länger 256 Zeichen umgehen kann (geht IIRC bis 1024) und der natürlich mit der WinAPI arbeitet, kann ich mit Sicherheit sagen, dass es funktioniert. Nur mal ein Beispiel: ![]() Zitat:
Grüße Dalai |
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
|
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
Zitat:
![]() Grüße Dalai |
AW: Extrem langen Pfad kürzen, Result leer?
Hmm..
Damit geht es:
Delphi-Quellcode:
Selbst unter Delphi 6 ;)
// nur wenn NtfsDisable8dot3NameCreation=0
function GetShortName(sLongName: WideString): WideString; var sShortName: WideString; nShortNameLen: Integer; begin sShortName := ''; nShortNameLen := 0; nShortNameLen := GetShortPathNameW(PWideChar(sLongName), nil, nShortNameLen); if nShortNameLen > 0 then begin SetLength(sShortName, nShortNameLen); nShortNameLen := GetShortPathNameW(PWideChar(sLongName), PWideChar(sShortName), nShortNameLen); if (nShortNameLen = 0) then raise Exception.Create(SysErrorMessage(GetLastError)); Result := sShortName; end else begin raise Exception.Create(SysErrorMessage(GetLastError)); end; Result := sShortName; end; procedure TForm1.Button1Click(Sender: TObject); var s : Widestring; begin s := '\\?\D:\0123456789\11111111111111111111111111111111111111111111111111'; s := s + '\22222222222222222222222222222222222222222222222222'; s := s + '\33333333333333333333333333333333333333333333333333'; s := s + '\44444444444444444444444444444444444444444444444444'; s := s + '\55555555555555555555555555555\Datei.txt'; Edit1.Text := GetShortName(s); // \\?\D:\012345~1\111111~1\222222~1\333333~1\444444~1\555555~1\Datei.txt end; Bedingt aber, das NtfsDisable8dot3NameCreation=0 gesetzt ist, eventuell VOR dem Erzeugen der Verzeichnisse und der Datei. |
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
|
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
Zitat:
Du sagst ja selbst.. Zitat:
gruss |
AW: Extrem langen Pfad kürzen, Result leer?
Hmm...
Tja, wo seitens NTFS keine 8.3 Namen erzeugt/hinterlegt wurden, da kann mann auch keinen kurzen Namen bekommen... Deshalb sollte die Funktion dann immer den original Namen, also ungekürzt liefern, wenn dieser nicht vorhanden ist. Denn der kurze Name ist im NTFS hinterlegt und wird nicht neu erzeugt, wenn man GetShortPathName verwendet. Viele APIs ermöglichen das Verwenden in der W-Version von '\\?\', somit kann da auch gelöscht und kopiert werden. Nur der Windows-Explorer kann das nicht ;) |
AW: Extrem langen Pfad kürzen, Result leer?
Zitat:
Grüße Dalai |
AW: Extrem langen Pfad kürzen, Result leer?
NtfsDisable8dot3NameCreation bedeutet "nur", dass nicht gleich zu Beginn auch immer der 8.3-Dateiname erzeugt wird. (hatte ich so mal irgendwo gelesen, aber kann auch nur Aberglaube sein)
Wenn es nötig ist, sollte Windows diesen Pfadnamen dennoch erstellen. Allerdings kann es sein dass ![]() Man könnte es explizit mit der ANSI-Version dieser API versuchen. Bei ANSI greifen in vielen APIs oftmals Sicherheitsmaßnamen (abwärtskompatibilität), wo dann dennoch diese kurzen "DOS"-Namen generiert werden. Und ja, auch der Explorer kann mit überlangen Pfaden umgehen, aber wie bei den meisten APIs nur für relative Pfade oder bei Verwendung von UNC. Ebenso verstehen viele (nicht alle) überlange Pfade nur via UNC. Gilt aber oftmals nicht für APIs, die Pfadnamen "manipulieren" und das in "statischen" Puffern erledigen, wie eventuell bei GetShortPathName. |
AW: Extrem langen Pfad kürzen, Result leer?
Also, ich verstehe das so. Wenn aktiviert, speichert/erzeugt Windows neben bei noch die kurzen Dateinamen. Wenn deaktiviert hat man Pech, weil Windows nur die langen Dateinamen/Pfade kennt. Ergo sum. Wenn vorher deaktiviert, hat der Threadersteller keine Chance auf die kurzen Dateinamen/Pfade zu zugreifen, weil sie nicht esxistieren.
|
AW: Extrem langen Pfad kürzen, Result leer?
Hmm..
Also, der Default-Wert von NtfsDisable8dot3NameCreation ist übrigens '2' und nicht '0'. Früher gab es nur 0 und 1 und seit zumindestens Windows7 (glaube ich) gibt es noch 2 und 3. Zitat:
Unter meinem Win8.1 stand es auf 2 und die kurzen Namen wurden nicht generiert. Erst nach dem Umstellen (und Neubooten) wurden auch die Kurzen Namen bei Neuanlage des Verzeichnisses erzeugt. Die ANSI-Version von GetShortPathName kann übrigens auch keine ShortNames bringen, wenn im File-System keine vorhanden sind. Auch ist die ANSI-Version auf MAX_PATH begrenzt und nur die Wide-Version kann die 32K langen FileNames. Somit sollte sich der TE nicht darauf verlassen, dass er die Shotnames auf anderen Systemen bekommt. |
AW: Extrem langen Pfad kürzen, Result leer?
Nach einigen Tests habe ich jetzt herausgefunden, dass Windows intern wohl selbst schon den kurzen Pfad sucht, wenn man \\?\ als Prefix verwendet.
Gestern hat das nicht funktioniert. Situaton gestern war, dass NtfsDisable8dot3NameCreation aus irgendeinem Grund nicht auf 2 stand. Folgende Funktion klappt einwandfrei (auch ohne getShortName)
Delphi-Quellcode:
function getUNCPath(aPath: string): string;
var bIsUNC: Boolean; begin aPath := ExpandFileName(aPath); bIsUNC := Copy(aPath, 1, 2) = '\\'; if not bIsUNC then aPath := '\\?\' + aPath; Result := aPath; end; Ansonsten sieht mein Wirr-Warr jetzt so aus
Delphi-Quellcode:
function getShortName(sLongName: WideString; bReturnLongIfNotFound: Boolean = False): WideString;
var sShortName: WideString; nShortNameLen: Integer; begin Result := ''; // Prüfung auf MAX_PATH. Wenn KLEINER MAX_PATH, gebe sLongName zurück, // da es sonst u.U. Zeit kosten kann, wenn die Datei sLongName nicht existiert. if Length(sLongName) > MAX_PATH then begin sShortName := ''; nShortNameLen := 0; nShortNameLen := GetShortPathNameW(PWideChar(sLongName), nil, nShortNameLen); if nShortNameLen > 0 then begin SetLength(sShortName, nShortNameLen); nShortNameLen := GetShortPathNameW(PWideChar(sLongName), PWideChar(sShortName), nShortNameLen); if nShortNameLen > 0 then Result := sShortName; end else begin end; end else Result := sLongName; // Sollte Result aus irgendeinem Grund leer sein, gebe sLongName zurück (falls gewollt) if (Result = '') and bReturnLongIfNotFound then Result := sLongName else Result := sShortName; end; // sPath := irgendetwas, das länger als MAX_PATH ist ... sPath := getUNCPath(sPath); // funktioniert sPath := getShortName(getUNCPath(sPath), True); // funktioniert // ohne eine der beiden Funktionen, funktioniert Weiteres (natürlich) nicht |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz