Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: Probleme, wenn ShortPathName länger ist, als der eigentliche/lange Dateiname?

  Alt 5. Jun 2024, 12:24
So, ich hab es jetzt auch in einem Programm versucht,
sowie dort auch explizit nochmal mit der ANSI-API,
aber im Windows 11 bekomme ich niemals einen Kurznamen. (außer wenn ich es im Samba auf einen Share des Synology-NAS versuche)
Auf einem Windows Server 2016 dagegen, klappt es, mit dem Kurznamen-Test.

siehe Anhang, die Test.cmd ausführen
So, jetzt bau ich noch ein Drag&Drop-Testprogramm fertig und dann mal beim Kunden nachsehn.


Vielleicht hat es was mit dieser Bermerkung zu GetLongPathName zu tun, wobei ich sie nicht ganz verstehe
Ist schon richtig, auch wenn es schon bissl "eigenartig" ist,
aber selbst wenn dabei ein Fehler drin wäre, dann dürfte nur ein und nicht zwei Zeichen fehlen.
  • wenn Fehler (z.B. Buffer zu klein oder nicht angegeben), dann Result=Chars+#0
  • wenn kein Fehler (Buffer und groß genug), dann nur Result=Chars (ohne #0)
  • so oder so, reingeben muß man immer inkl. #0 (oder 0 wenn Buffer=nil)
    und raus bekommt man die benötigte Länge (bei Fehler, bzw. Abfrage) oder nur die Anzahl der Zeichen, wenn es OK war.

Es gibt milliarden Varianten der Implementation.
Da "hier" der Pfad kürzer als MAX_PATH ist, dürfte alles der Nachfolgenden gehen.
Die ersten 3 machen es aber eigetlich richtig und fragen vorher die Länge ab.
Empfehlen würde ich die 2 (meine Implementation ) ... Viele machen es mehr wie bei 3 oder bissl wie 1, aber wozu den Speichermanager unnötig beanspruchen.
Delphi-Quellcode:
function GetShortName(Filename: string): string;
var
  Len, Res: Cardinal;
  Buffer: TBytes;
begin
  // so mehr C++-ig
  Len := GetShortPathName(PChar(Filename), nil, 0);
  SetLength(Buffer, Len * SizeOf(Char)); // oder halt eigentlich mit Pointer, GetMem und anschließend FreeMem (und natürlich mit einem Try-Finally)
  Res := GetShortPathName(PChar(Filename), Pointer(Buffer), Len);
  if Res > Len then
    raise Exception.Create('das sollte zwar nie passieren, da wir die Größe ja vorher abgefragt hatten, aber wir prüfen es einfach nochmal');
  SetLength(Result, Res);
  MoveMemory(PChar(Result), Pointer(Buffer), Res * SizeOf(Char));
end;

function GetShortName(Filename: string): string;
begin
  // ich schneide die #0 ab, da String implizit zwei #0#0 am Ende besitzt und Diese auch beschreibbar sind
  SetLength(Result, GetShortPathName(PChar(Filename), nil, 0) - 1);
  GetShortPathName(PChar(Filename), PChar(Result), Length(Result) + 1);
end;

function GetShortName(Filename: string): string;
begin
  // Puffer erstmal inkl. der #0 und dann wieder abschneiden
  SetLength(Result, GetShortPathName(PChar(Filename), nil, 0));
  SetLength(Result, GetShortPathName(PChar(Filename), PChar(Result), Length(Result)); // hier müsste man noch -1, wenn die #0 bei OK inkl. wäre
end;

function GetShortName(Filename: string): string;
begin
  // MAX_PATH = maximal 260 Chars
  // 3 = Laufwerk (C:\)
  // 256 = Pfad
  // 1 = #0
  SetLength(Result, MAX_PATH);
  SetLength(Result, GetShortPathName(PChar(Filename), PChar(Result), MAX_PATH); // hier müsste man noch -1, wenn die #0 bei OK inkl. wäre
end;

function GetShortName(Filename: string): string;
var
  Temp: array[0..MAX_PATH-1] of Char;
  Len: Cardinal;
begin
  Len := GetShortPathName(PChar(Filename), @Temp, MAX_PATH);
  SetString(Result, @Temp, Len); // bei einem Fehler, z.B. wenn Pfad länger MAX_PATH, dann wäre eine #0 im String
  //Result := PChar(Result); // den Fehlerfall könnte man so beheben (#0 weg), aber der Pfad bleibt dennoch abgeschnitten (maximal 259 Zeichen)
end;

function GetShortName(Filename: string): string;
var
  Temp: array[0..MAX_PATH-1] of Char;
begin
  // einfach blind hindurch
  GetShortPathName(PChar(Filename), @Temp, MAX_PATH);
  Result := Temp;
end;

function GetShortName(Filename: string): string;
var
  Temp: array[0..MAX_PATH-1] of Char;
begin
  // auf Gott vertrauen und hoffen es knallt nicht,
  // aber wenn keine #0 im Temp vorkommt, dann ab in die Hölle
  GetShortPathName(PChar(Filename), @Temp, MAX_PATH);
  Result := PChar(@Temp);
end;

function GetShortName(Filename: string): string;
var
  Temp: array[0..MAX_PATH-1] of Char;
begin
  // einfach blind hindurch
  if GetShortPathName(PChar(Filename), @Temp, MAX_PATH) <> 0 then
    Result := PChar(@Temp)
  else
    Result := '';
end;

...
$2B or not $2B
  Mit Zitat antworten Zitat