![]() |
PIDL und der Font-Ordner - geht nicht
Hallo,
für manche Operationen konvertiere ich ein Pfad+Dateiname zu ein PIDL Dingsbums.
Delphi-Quellcode:
Dies geht soweit aber im Font-Ordner (C:\Windows\Fonts). Also wenn ich dort im Ordner eine Schriftartdatei auf die Funktion feuere, bekomme ich bei "ParseDisplayName" einen Fehlercode (E_INVALIDARG) zurück. Schlimmer noch, dass "ParseDisplayName" hier dann noch zu lange braucht und meine Routine abbremst. Der Ordner wird auch von Windows irgendwie speziell behandelt. Auf eine Schriftartdatei kann man z.B. kein Eigenschaftsdialog anzeigen lassen. Dies geht erst, wenn man eine Datei herauskopiert. Alles irgendwie mal wieder nicht zu verstehen. Hat jemand Rat?
function PathToPIDL(APath: WideString): PItemIDList;
var Desktop: IShellFolder; pchEaten, dwAttributes: ULONG; begin Result := nil; SHGetDesktopFolder(Desktop); dwAttributes := 0; if Assigned(Desktop) then begin if Desktop.ParseDisplayName(0, nil, PWideChar(APath), pchEaten, Result, dwAttributes) <> NOERROR then Result := nil; end end; Gruß Mike |
AW: PIDL und der Font-Ordner - geht nicht
![]() ![]() /edit upps, sorry, hab jetzt erst verstanden was du vorhast, vergiss das obige, tut mir leid! |
AW: PIDL und der Font-Ordner - geht nicht
Hab vielleicht doch noch was passendes...
![]()
Delphi-Quellcode:
// falls das Windows.pas nicht hat:
function ILCreateFromPath(pszPath: LPCWSTR): PItemIDList; stdcall external shell32 name 'ILCreateFromPathW'; // der eigentliche aufruf: PathPIDL := ILCreateFromPath(pWideChar(Path)); Zitat:
|
AW: PIDL und der Font-Ordner - geht nicht
"ILCreateFromPath" ist vorhanden aber funktioniert leider nicht.
Ich bekomme auch NIL zurück. Was nicht unbedingt das schlimmste wäre*, aber die Funktion bremst dann alles aus. Das ist dann nicht so toll. Es geht mir jedenfalls um folgendes. Ich prüfe mit "ShellFolder.GetAttributesOf" auf die Werte "SFGAO_LINK" und "SFGAO_SHARE". SFGAO_SHARE nur auf Ordner (ist das richtig?). SFGAO_LINK kann auch eine Datei sein (z.B. mit MKLINK symdatei.txt richtigedatei.txt). Kann man sogar im besagtem Font-Order (c:\windows\Fonts) erstellen. So prüfe ich:
Delphi-Quellcode:
Also brauche ich ja ein PathToPidl. Und in diesem Font-Ordner geht das nicht.
function IsLink(aPIDL: PItemIDList): Boolean;
var Attrs: DWord; ItemIDList: PItemIDList; ShellFolder: IShellFolder; begin Result := False; if fjLinkOverlay = False then Exit; if Succeeded(SHBindToParent(aPidl, IID_IShellFolder, Pointer(ShellFolder), ItemIDList)) then begin attrs := SFGAO_LINK; ShellFolder.GetAttributesOf(1, ItemIDList, Attrs); if Attrs and SFGAO_LINK <> 0 then result := true else result := false; end else result := false; end; *Ich will jetzt auch nicht anfangen mit "if path<>'fontordner'" zu arbeiten. Evtl. gibt es ja noch mehrere Windows-Ordner die einem das leben schwer machen. Oder es kommen irgendwann Ordner dazu, die irgendwelche Sonderwünsche beanspruchen und mein PathToPidl (ob meine Funktion oder die "ILCreateFromPath") die Routine bzw. mein Programm ausbremst. Also eine IF-Prüfung wäre nur der richtige weg, wenn ich den Ordner selbst identifizieren könnte, sprich ob's ein normaler Ordner ist oder ein Ordner mit extrawünschen :) Der Ordner "Downloaded Program Files" in (c:\Windows) geht z.B. auch nicht, wie ich gerade festgestellt habe. Also beides System-Ordner. Dachte schon die Lösung gefunden zu haben, warum es nicht geht. Jedoch ist "C:\windows\media" auch ein System-Ordner aber hier geht es wieder, ein Pfad+Datei ins PIDL zu bekommen. Also eine IF-Prüfung auf dieses System Attribut kann ich hier auch nicht machen. |
AW: PIDL und der Font-Ordner - geht nicht
Ich kann zum Glück eine mit MKLINK Symdatei anders prüfen.
Mit dem "FILE_ATTRIBUTE_REPARSE_POINT" kann ich ohne PIDL in solchen Ordnern (die mit PIDL mein Zeug ausbremsen) die Dateien identifizieren. Trotzdem brauche ich eigentlich auch für SHGetFileInfo ein PIDL. Also das Problem besteht eigentlich weiterhin in diesen Ordnern. Leider bekommt man manchmal ein falsches IconIndex von SHGetFileInfo (ohne PIDL). Hier und da fehlen die Doppelpfeile bei komprimierten Dateien. Selten aber manchmal fehlen die einfach. Dagegen bekomme ich immer das richtige IconIndex (bei komprimierten Dateien) wenn ich SHGetFileInfo mit PIDL nutze. Also ich muss irgendwie an ein PathToPidl ran. Auch in diesen komischen Ordnern. :( |
AW: PIDL und der Font-Ordner - geht nicht
Ich habe gestern rumprobiert. Vieeeel rumprobiert.
Das phänomen tritt nur auf wenn du es auf dateien loslässt, nicht auf den ordner wie die topic es benennt. Das ausbremsen konnt ich nicht verhindern, nichts desto trotz hab ich 'ne mini "verschlimmbesserung" eingebaut.
Delphi-Quellcode:
Aufruf dann so:
uses
System.IOUtils, Winapi.ShlObj, Winapi.ActiveX; function PathToPidl(const Path: String; out Fallback: Boolean): PItemIdList; var DesktopFolder: IShellFolder; dummy: Cardinal; begin Fallback := False; Result := nil; if (TDirectory.Exists(path, False) or TFile.Exists(path, False)) then if Succeeded(SHGetDesktopFolder(DesktopFolder)) then if DesktopFolder.ParseDisplayName(0, nil, PChar(Path), dummy, Result, dummy) <> NOERROR then if DesktopFolder.ParseDisplayName(0, nil, PChar(ExtractFilePath(Path)), dummy, Result, dummy) = NOERROR then Fallback := True; end;
Delphi-Quellcode:
hier meine anderen versuche, mit ordner klappt alles, mit dateien im fonts ordner versagen alle...
procedure TForm1.Button1Click(Sender: TObject);
var PIDL: PItemIDList; PathName: array[0..MAX_PATH - 1] of Char; checker: Boolean; path: String; begin path := 'c:\windows\fonts\arial.ttf'; Memo1.Clear; Memo1.Lines.Add('Führe "PathToPIDL(path);" aus.'); PIDL := PathToPIDL(path, checker); if (Assigned(PIDL)) then begin if SHGetPathFromIDList(PIDL, @PathName) then begin Memo1.Lines.Add('PathToPIDL: ' + PathName); if checker then Memo1.Lines.Add('Fallback zum Ordnernamen wurde genutzt.'); Memo1.Lines.Add('PathToPIDL war ok.'); end; ILFree(PIDL); end else Memo1.Lines.Add('PathToPIDL hat nicht geklappt.'); end;
Delphi-Quellcode:
Ich werd noch bissl rumprob'sen... bye
// der klassiker
function PathToPIDL(const Path: String): PItemIDList; var Attrs: DWORD; begin Result := nil; try CoInitialize(nil); (* if (SHParseDisplayName(PChar(Path), nil, Result, 0, Attrs) = S_OK) then if not Assigned(Result) then Result := nil;*) SHParseDisplayName(PChar(Path), nil, Result, 0, Attrs); finally CoUnInitialize(); end; end; // das was ich oben beschrieben hatte function PathToPIDL(const Path: String): PItemIDList; begin Result := ILCreateFromPath(PChar(Path)); end; // deine version etwas entschlackt function PathToPIDL(const Path: String): PItemIdList; var DesktopFolder: IShellFolder; dummy: Cardinal; begin if Succeeded(SHGetDesktopFolder(DesktopFolder)) then if DesktopFolder.ParseDisplayName(0, nil, PChar(Path), dummy, Result, dummy) <> NOERROR then Result := nil end; |
AW: PIDL und der Font-Ordner - geht nicht
Danke für die Mühe
Wie du siehst, ganz und gar nicht einfach zu lösen. Naja, einfach ist es, wenn man weiß wie *lach Für "ParseDisplayName" ist ja noch beschrieben (mit Google Übersetzer): LPWSTR Da jeder Shell-Ordner seine eigene Analysesyntax definiert, kann die Form, die diese Zeichenfolge annehmen kann, variieren. Unter Bemerkungen noch: Einige Shell-Ordner implementieren möglicherweise nicht IShellFolder : ParseDisplayName. Jeder Ordner, der dies tut, definiert seine eigene Analysesyntax. Hört sich irgendwie an, als ob man da mit dem Parameter "IBindCtx" was machen muss? Eines habe ich mal getestet: Anstatt "C:\Windows\Fonts\fontname.ttf" habe ich "\\COMPUTERNAME\Windows\Fonts\fontname.ttf" genommen. Der erste Zugriff dauert lange (wegen dem Computernamen) aber danach macht "ParseDisplayName" oder auch "ILCreateFromPath" keine Bremse mehr. Ist jetzt zwar auch nicht die Lösung, da weiterhin kein PIDL erzeugt wird und "ParseDisplayName" z.B. hier auch "E_INVALIDARG" zurück liefert. Das Problem werden wohl viele haben, die mit PIdl/SHGetFileInfo etc. arbeiten. Aber es nicht unbedingt merken. Wer kommt schon auf die Idee, dass manche Dateizugriffe in speziellen Verzeichnissen Probleme machen, wenn es sonst fast überall funktioniert. Doofe Sache aber auch *schnief* |
AW: PIDL und der Font-Ordner - geht nicht
Zitat:
Der Explorer selbst behandelt die beiden genannten Ordner auch etwas anders. Im Font-Ordner kann z.B. zu einer Datei kein Eigenschafts-Dialog angezeigt werden und im "Downloaded Program Files" werden vom Explorer keine Inhalte (Dateien) angezeigt, auch wenn Dateien extern (mit anderer Software) dort hineinkopiert worden sind. Wenn's virtuelle Ordner wären und hier Windows sein Ding macht, würde ich es ja verstehen aber es sind doch ganz normale Verzeichnisse. |
AW: PIDL und der Font-Ordner - geht nicht
Wenn ich nicht gerade falsch schauen, hab ich's hinbekommen.
Also hier (noch nicht verschönert/optimiert usw):
Delphi-Quellcode:
Ich übergebe Pfad+Datei + Dateiattribute der Datei.
function PathToPIDL(APath: WideString;FA:Cardinal): PItemIDList;
var Desktop: IShellFolder; pchEaten, dwAttributes: ULONG; kk : hresult; pbc : IBindCtx; w32fd : TWin32FindData; ifs : TFileSystemBindData; r : HResult; begin Result := nil; SHGetDesktopFolder(Desktop); dwAttributes := 0; ZeroMemory(@w32fd, Sizeof(TWin32FindData)); w32fd.dwFileAttributes := FA; ifs := TFileSystemBindData.Create; ifs.SetFindData(w32fd); r := CreateBindCtx(0, pbc); r := pbc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, ifs); if Assigned(Desktop) then begin kk:= Desktop.ParseDisplayName(0, pbc, PWideChar(APath), pchEaten, Result, dwAttributes); if kk <> NOERROR then begin Result := nil; f.Caption := APath+' '+inttostr(kk); end end end; Was ich da mache, ist mir nicht so ganz klar (noch nicht) aber habe aus dem Netz was zu diesem "IBindCtx" gefunden und dachte mir, ich probiere das mal aus. So scheint es wohl zu funktionieren und ich messe keine Bremse. Na bestimmt entdecke ich wieder andere Probleme *lol … mal schauen. Jedoch kann ich mit diesem PIDL nicht auf SFGAO_LINK prüfen. SFGAO_SHARE geht dann wiederum (z.B. Ordner C:\Users). Hier dazu zwei Funktionen, die recht ähnlich sind. Warum geht SFGAO_SHARE und SFGAO_LINK nicht?
Delphi-Quellcode:
Für SFGAO_LINK kann ich stattdessen auf das Attribut "FILE_ATTRIBUTE_REPARSE_POINT" (TWin32FindData.dwFileAttributes) prüfen. Trotzdem verstehe ich noch nicht, warum die Funktion "IsLink" mit dem neuen PIDL nicht geht.
function IsShare(aPIDL: PItemIDList): Boolean;
var Attrs: DWord; ItemIDList: PItemIDList; ShellFolder: IShellFolder; begin Result := False; if fjShareOverlay = False then Exit; if Succeeded(SHBindToParent(aPidl, IID_IShellFolder, Pointer(ShellFolder), ItemIDList)) then begin attrs := SFGAO_SHARE; ShellFolder.GetAttributesOf(1, ItemIDList, Attrs); if Attrs and SFGAO_SHARE <> 0 then result := true else result := false; end else result := false; end; function IsLink(aPIDL: PItemIDList): Boolean; var Attrs: DWord; ItemIDList: PItemIDList; ShellFolder: IShellFolder; begin Result := False; if fjLinkOverlay = False then Exit; if Succeeded(SHBindToParent(aPidl, IID_IShellFolder, Pointer(ShellFolder), ItemIDList)) then begin attrs := SFGAO_LINK; ShellFolder.GetAttributesOf(1, ItemIDList, Attrs); if Attrs and SFGAO_LINK <> 0 then result := true else result := false; end else result := false; end; |
AW: PIDL und der Font-Ordner - geht nicht
Liste der Anhänge anzeigen (Anzahl: 1)
Ich bin dem Problem einen Schritt näher gekommen indem ich mir einen auf PIDL's basierten Explorer nachgebastelt habe.
Das "Geheimnis" ist, das im Fonts Ordner abgelegte Dateien von Windows anders angesprochen werden. Mein Anhang sagt mehr als tausend Worte, wie man allerdings von den Objekten wiederum einen Dateinamen zaubert bleibt mir noch verborgen. Nun zu Deinem Eigenschaften-Dialog, hier ist ein getesteter Kode der den Standard Windows Eigenschaften Dialog provoziert.
Delphi-Quellcode:
procedure PropertiesDialog(const Path: string); overload;
var SEI: TShellExecuteInfo; begin FillChar(SEI, SizeOf(SEI), 0); SEI.cbSize := SizeOf(SEI); SEI.lpFile := PChar(Path); SEI.lpVerb := 'properties'; SEI.fMask := SEE_MASK_INVOKEIDLIST; ShellExecuteEx(@SEI); end; procedure PropertiesDialog(const PIDL: PItemIDList); overload; var SEI: TShellExecuteInfo; Path: array[0..MAX_PATH - 1] of WideChar; begin if SHGetPathFromIDList(PIDL, @Path) then begin FillChar(SEI, SizeOf(SEI), 0); SEI.cbSize := SizeOf(SEI); SEI.lpFile := PChar(String(Path)); SEI.lpVerb := 'properties'; SEI.fMask := SEE_MASK_INVOKEIDLIST; ShellExecuteEx(@SEI); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:11 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