AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Groß/Kleinschreibung (Pfad) Original erhalten?

Groß/Kleinschreibung (Pfad) Original erhalten?

Ein Thema von MicMic · begonnen am 18. Aug 2018 · letzter Beitrag vom 1. Okt 2018
Antwort Antwort
Seite 1 von 2  1 2   
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 18. Aug 2018, 22:36
Danke für die Hilfestellung.
habe mal alles ausprobiert (ExtractFilePath, ExpandFileName, GetDirectoryName) und mit SHGetFileInfo auch herumexperimentiert.
Keine Erfolge und zu "ExpandFileNameCase"... (kannte ich noch nicht) da kann man etwas herausholen aber dennoch müsste man das Verzeichnis (z.B. "C:\Ich\bin\so\froh\wie\der\Mops\im\Hafenstroh \") splitten und in Strings aufteilen. Am Ende eines Pfads kann man noch "\." oder "\.." angeben um ein oder zwei Verzeichnisse zurück zu gehen und hier die originale Groß-/Kleinschreibung zu bekommen. Nur nicht alles auf einmal. Aber wegen diesem Splitten und stets erneuten Aufruf von FindFirst (auf die Idee bin ich nämlich auch gekommen) - was die Funktion ja macht, ist das alles nicht gerade Optimal. Naja, nicht so schlimm. Trotzdem Danke für eure Hilfestellung.

Michael
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.688 Beiträge
 
Delphi 12 Athens
 
#2

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 18. Aug 2018, 22:59
Keine Erfolge und zu "ExpandFileNameCase"... (kannte ich noch nicht) da kann man etwas herausholen aber dennoch müsste man das Verzeichnis (z.B. "C:\Ich\bin\so\froh\wie\der\Mops\im\Hafenstroh \") splitten und in Strings aufteilen.
Ich hatte jetzt angenommen, die Funktion tut bereits alles was du brauchst. Vielleicht habe ich die Anforderung aber auch nur falsch verstanden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 18. Aug 2018, 23:33
Habe es auch noch mit FileCtrl.ProcessPath(s,drv,Dir,filename); probiert, auch negativ.
Lustigerweise schlägt selbst ein FileCtrl.SelectDirectory() fehl, so ein Ergebnis hätte ich von so einer Funktion nicht erwartet. Screenshot - 19_08.jpg

Ps, im Nachhinein ist mir auch eingefallen mit SHGetFileInfo bekommt man nur Infos, wie der Name selbst beinhaltet, nur leider nicht Deine benötigten. FindFirst() scheint wohl einzige Api zu sein, oder aus MFT auslesen.
Gruß vom KodeZwerg

Geändert von KodeZwerg (18. Aug 2018 um 23:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 19. Aug 2018, 00:40
Nun habe ich eine Lösung.
Delphi-Quellcode:
uses
  ActiveX, ShlObj, SHDocVw, ComObj;

function PathToPIDL(const Path: string): PItemIDList;
const
  SFGAO_STREAM = $00400000;
var
  Count: ULONG;
  Attributes: ULONG;
  ShellFolder: IShellFolder;
begin
  OleCheck(SHGetDesktopFolder(ShellFolder));
  Attributes := SFGAO_FOLDER or SFGAO_STREAM;
  OleCheck(ShellFolder.ParseDisplayName(0, nil, PWideChar(WideString(Path)), Count, Result, Attributes));
  if not ((Attributes and SFGAO_FOLDER = SFGAO_FOLDER) and (Attributes and SFGAO_STREAM <> SFGAO_STREAM)) then
   begin
     CoTaskMemFree(Result);
     raise Exception.Create('Could not convert string to PIDL');
   end;
end;

function PIDLToPath(const PIDL: PItemIDList): string;
var
  Path: array[0..Max_Path] of Char;
begin
  if ShGetPathFromIDList(PIDL, Path) then
   Result := Path
   else raise Exception.Create('Could not convert PIDL to string');
end;

procedure TfrmMain.FormCreate(Sender: TObject);
var
  s: string;
  PIDL: PItemIDList;
begin
  s := 'c:\uSERs\PUBlic\DeskTop';
  PIDL := PathToPIDL(s);
  s := PIDLToPath(PIDL);
  Memo1.Lines.Add(S);
end;
Zitat:
C:\Users\Public\Desktop
Viel Spass damit.

ps: Bearbeite das Uses, kann sein das da zuviel steht.
Gruß vom KodeZwerg

Geändert von KodeZwerg (19. Aug 2018 um 01:09 Uhr) Grund: uses hinzugefügt
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 19. Aug 2018, 09:06
Danke @KodeZwerg
Geht SUPER. Dankeschön

Habe noch zwei Fragen. Im "if not" Bereich steht "CoTaskMemFree". Sonst nicht.
Sollte es nicht so oder so ausgeführt werden? Aber es ist ja hier ein "Result" was ja gebraucht wird.

Dann kenne ich das "WideString" gar nicht. Bei "PWideChar(WideString(Path))". Ich mach sonst immer ein "PWideChar(Path)". Das geht auch aber was ist der Unterschied? Da ist mir sowieso noch etwas im Gedächtnis. Bin mir da nicht sicher, aber glaube gelesen zu haben das man bei PWideChar(stringvariable) noch ein "#0" dazutun soll. Also PWideChar(stringvariable+#0). Kann das sein?

Ich habe jedenfalls mal folgende Funktion aus den beiden gemacht. OleCheck kenne ich auch nicht und habe es mal Anhand ähnlicher Funktionen die ich nutze abgeändert. Dabei ist folgendes herausgekommen. Hier wird dann "CoTaskMemFree" auch stets freigegeben und im jeden Fehlerfall einfach der übergebene Pfad wieder zurückgegeben. Ein nachfolgender Attribut-Check der beiden "SFGAO_..." Flags habe ich auch weggelassen, da ich denke, dass dies nicht mehr nötig ist, wenn es bei der Funktion "ParseDisplayName" gesetzt wurde. Das ist aber weniger ein technisches Verständnis, eher so eine Überlegung
Code:
Function PathToCS(Const Path: UnicodeString): UnicodeString;
Var
  Count: ULONG;
  Attrs: ULONG;
  ShellFolder: IShellFolder;
  Pa: Array[0..Max_Path] Of Char;
  Pidl: PItemIDList;
Begin
  Attrs := SFGAO_FOLDER or SFGAO_STREAM;
  Count := 0;
  If SHGetDesktopFolder(ShellFolder) = S_OK Then
  Begin
    If ShellFolder.ParseDisplayName(0,Nil,PWideChar(Path),Count,Pidl,Attrs) = S_OK Then
    Begin
      If SHGetPathFromIDList(Pidl, Pa)
        Then Result := IncludeTrailingPathDelimiter(Pa)
        Else Result := IncludeTrailingPathDelimiter(Path);
      CoTaskMemFree(Pidl);
    End Else Result := IncludeTrailingPathDelimiter(Path);
  End Else Result := IncludeTrailingPathDelimiter(Path);
End;
Gruß Michael
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 19. Aug 2018, 10:07
Danke @KodeZwerg
Geht SUPER. Dankeschön
Gern geschehen, meine Priorität lag halt anders, deswegen auf zwei Funktionen verteilt.
Solange es das macht was Du möchtest ist ja alles im grünen Bereich
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 19. Aug 2018, 10:33
Habe noch zwei Fragen. Im "if not" Bereich steht "CoTaskMemFree". Sonst nicht.
Sollte es nicht so oder so ausgeführt werden? Aber es ist ja hier ein "Result" was ja gebraucht wird.
Bei mir ist es richtig im Einsatz. Ich will damit bewusst das Result löschen.
Dann kenne ich das "WideString" gar nicht. Bei "PWideChar(WideString(Path))".
Das garantiert mir das 16bit verwendet wird für Unicode characters conversion.

Ps:
Mag sein das neuere Delphi Version all das anders handhaben oder schon Routinen dafür besitzen. Für D2009 sollte das gelten was ich schrieb.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 19. Aug 2018, 12:28
Nur, bei der Lösung kannst du nie Prüfen, ob die Funktion nicht fehlgeschlagen ist. OK, mag nicht so wichtig sein, da es sich wohl nur um eine optische Spielerei handelt. Aber ich wollte es nur mal erwähnt haben.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 29. Sep 2018, 18:15
Nun habe ich eine Lösung.
Delphi-Quellcode:
uses
  ActiveX, ShlObj, SHDocVw, ComObj;

function PathToPIDL(const Path: string): PItemIDList;
const
  SFGAO_STREAM = $00400000;
var
  Count: ULONG;
  Attributes: ULONG;
  ShellFolder: IShellFolder;
begin
  OleCheck(SHGetDesktopFolder(ShellFolder));
  Attributes := SFGAO_FOLDER or SFGAO_STREAM;
  OleCheck(ShellFolder.ParseDisplayName(0, nil, PWideChar(WideString(Path)), Count, Result, Attributes));
  if not ((Attributes and SFGAO_FOLDER = SFGAO_FOLDER) and (Attributes and SFGAO_STREAM <> SFGAO_STREAM)) then
   begin
     CoTaskMemFree(Result);
     raise Exception.Create('Could not convert string to PIDL');
   end;
end;

function PIDLToPath(const PIDL: PItemIDList): string;
var
  Path: array[0..Max_Path] of Char;
begin
  if ShGetPathFromIDList(PIDL, Path) then
   Result := Path
   else raise Exception.Create('Could not convert PIDL to string');
end;

procedure TfrmMain.FormCreate(Sender: TObject);
var
  s: string;
  PIDL: PItemIDList;
begin
  s := 'c:\uSERs\PUBlic\DeskTop';
  PIDL := PathToPIDL(s);
  s := PIDLToPath(PIDL);
  Memo1.Lines.Add(S);
end;
Zitat:
C:\Users\Public\Desktop
Viel Spass damit.

ps: Bearbeite das Uses, kann sein das da zuviel steht.
Hallo, wenn du dich erinnern kannst...
An der Funktion (bzw. an meine Funktion die ich entsprechend für meine Bedürfnisse abgeändert habe <- nachfolgender Code), bin ich gerade noch am rumwerkeln.
Code:
Function PathToCS(Const Path: UnicodeString): UnicodeString;
Var
  Count: ULONG;
  Attrs: ULONG;
  ShellFolder: IShellFolder;
  Pa: Array[0..Max_Path] Of Char;
  Pidl: PItemIDList;
Begin
  Attrs := SFGAO_FOLDER or SFGAO_STREAM;
  Count := 0;
  If SHGetDesktopFolder(ShellFolder) = S_OK Then
  Begin
    If ShellFolder.ParseDisplayName(0,Nil,PWideChar(Path),Count,Pidl,Attrs) = S_OK Then
    Begin
      If SHGetPathFromIDList(Pidl, Pa)
        Then Result := IncludeTrailingPathDelimiter(Pa)
        Else Result := IncludeTrailingPathDelimiter(Path);
      CoTaskMemFree(Pidl);
    End Else Result := IncludeTrailingPathDelimiter(Path);
  End Else Result := IncludeTrailingPathDelimiter(Path);
End;
Ich probiere nämlich bei langen Verzeichnissen dies auch so zu lösen. Versuche mich an "SHGetPathFromIDListW" (anstatt "SHGetPathFromIDList" (ohne W)). Aber was ich auch mache, sobald mehr als 260 (glaub ich) Zeichen im Pfad sind (z.B. C:\Test\UnterOrdner\Unter\ganzvielunter\...\...\.. .), bekomme ich kurze Pfade zurück geliefert. Also z.B. diese "ICHGEH~1" verkürzten Namen. Hier im Pfad am Anfang "\\?\" anzuhängen klappt erst recht nicht.

Meine Versuche für den 2. Parameter für "SHGetPathFromIDListW":
Code:
Var Pa: PWideChar; // zuvor "Array[0..Max_Path] Of Char;"

const
  NTFS_MAX_PATH = 32767;

GetMem(Pa, (NTFS_MAX_PATH + 1) * 2);

If SHGetPathFromIDListW (Pidl, Pa)
...
Aber so geht das einfach nicht.

Vielleicht hast du (oder jemand anderes) eine Idee?

Micha
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Groß/Kleinschreibung (Pfad) Original erhalten?

  Alt 29. Sep 2018, 20:52
Ne, soviele Unterordner habe ich noch nicht getestet, hier zwei Funktionen um aus nem legitimen 8.3 wieder was langes zurück zu erhalten, ohne FindFirst() aufzurufen.

uses Windows, SysUtils, ActiveX, ShlObj; Was zuviel ist, wirf raus.

Passend zum ersten PIDL Beispiel, hier ein weiteres
Delphi-Quellcode:
function LongPathFromShort(const ShortPath: string): string;
var
  iAttributes: Cardinal;
  iEaten: Cardinal;
  IntfDesktop: IShellFolder;
  IntfMalloc: IMalloc;
  pItemList: PItemIDList;
  sFile: WideString;
  szFile: array[0..MAX_PATH] of Char;
begin
  Result := ShortPath;
  if not FileExists(ShortPath) then
    Exit;
  if Succeeded(SHGetDesktopFolder(IntfDesktop)) then
  begin
    sFile := ShortPath;
    iAttributes := 0;
    if Succeeded(IntfDesktop.ParseDisplayName(0, nil, POleStr(sFile),
      iEaten, pItemList, iAttributes)) then
    begin
      SHGetPathFromIDList(pItemList, szFile);
      Result := szFile;
      SHGetMalloc(IntfMalloc);
      IntfMalloc.Free(pItemList)
    end
  end
end;
Oder lieber per WinApi:
Delphi-Quellcode:
function GetLongName(const APath: string): string;
var
  Buffer: array[0..MAX_PATH] of Char;
  Required: Integer;
begin
  Required := GetLongPathName(PChar(APath), Buffer, Length(Buffer));
  if Required > MAX_PATH then {Buffer too small}
  begin
    SetLength(Result, Required - 1);
    GetLongPathName(PChar(APath), Pointer(Result), Required);
  end
  else if Required = 0 then {Error}
    Result := APath
  else
    SetString(Result, Buffer, Required);
end;

Ich habe es nicht mit extrem langen/tiefen Ordner-Namen getestet, bei mir machts jedenfalls das was es soll, 8.3 entfalten.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:27 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