介绍
在Windows 7中,您有一些文件,图片和音乐等特殊文件夹,称为库。
如果你不知道他们,基本上每个库文件夹可以包含位置(path),这基本上是每个库的快捷方式。
一些例子:
Documents (Library)
(Location)
(Location)
Music (Library)
(Location)
(Location)
Pictures (Library)
(Location)
当您从Windows资源pipe理器或“开始”菜单中单击任何这些库文件夹时,Windows资源pipe理器将显示该库中定义的位置。
任务
我需要做的是读取每个库types的位置,并能够用我自己的位置写回(更新)库。 我发现这些库存储在用户的AppData文件夹中,如下所示:
C:\Users\SOMEUSER\AppData\Roaming\Microsoft\Windows\Libraries
这些库是这种文件types: 库(.library-ms) – 如果你右键点击一个,select属性,库选项卡,你可以看到与该库相关联的库位置。
我没有看到解压缩这些方法,并把它们放在一个TStringList中,以便在Delphi中进行编辑。 我想知道,如果这些库位置实际存储在Windowsregistry,所以从谷歌的一些研究,我发现这些path:
但是,我再次看不到实际的库位置列表。
那么,如何在Delphi中读取库文件中的位置列表,将它们添加到Listbox或TStringList,编辑条目,然后写回更改? 刚刚能够提取库位置path将是一个开始。
我只是有一种感觉,这将是一个简单的答案,我似乎无法find的问题之一!
使用SHLoadLibraryFrom...()
函数SHLoadLibraryFromKnownFolder()
如SHLoadLibraryFromKnownFolder()
来获取IShellLibrary
接口,然后可以使用其方法来枚举和操作库,例如IShellLibrary::GetFolders()
, IShellLibrary::AddFolder()
, IShellLibrary::RemoveFolder()
等
更新:例如:
uses ..., ActiveX, KnownFolders, ShlObj; // The SHLoadLibraryFrom...() functions are implemented inline in the Win32 SDK // shobjidl.h header file, so you have to implement them manually in your // code if you you are not using a version of Delphi that already implements // them in the RTL's ShlObj.pas unit for you... // SHLoadLibraryFromKnownFolder() is defined wrong in ShlObj.pas!!! See QC #109306 function My_SHLoadLibraryFromKnownFolder(const kfidLibrary: TGUID; grfMode: DWORD; riid: TIID; out ppv): HRESULT; var plib: IShellLibrary; begin Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IShellLibrary, plib); if SUCCEEDED(Result) then begin Result := plib.LoadLibraryFromKnownFolder(kfidLibrary, grfMode); if SUCCEEDED(Result) then Result := plib.QueryInterface(riid, ppv); end; end; function GetLibraryFileSystemFolders(FolderID: TGUID; Folders: TStrings): Boolean; var SL: IShellLibrary; Arr: IShellItemArray; Enum: IEnumShellItems; Item: IShellItem; Path: LPWSTR; begin Result := False; if FAILED(My_SHLoadLibraryFromKnownFolder(FolderID, STGM_READ, IShellLibrary, SL)) then Exit; if FAILED(SL.GetFolders(LFF_FORCEFILESYSTEM, IShellItemArray, Arr)) then Exit; if FAILED(Arr.EnumItems(Enum)) then Exit; while Enum.Next(1, Item, nil) = S_OK then begin if FAILED(Item.GetDisplayName(SIGDN_FILESYSPATH, Path)) then Exit; try Folders.Add(Path); finally CoTaskMemFree(Path); end; Item := nil; end; Result := True; end;
。
var Folders: TStringList; begin Folders := TStringList.Create; try if GetLibraryFileSystemFolders(FOLDERID_DocumentsLibrary, Folders) then begin //... end; finally Folders.Free; end; end;
更新 : SHLoadLibraryFromKnownFolder()
仅适用于定义了KNOWNFOLDERID
值的Microsoft定义的库。 如果要访问自定义库,则必须使用稍微修改的方法来获取IShellLibrary
接口,例如:
// SHLoadLibraryFromItem() is defined wrong in ShlObj.pas!!! See QC #109306 function My_SHLoadLibraryFromItem(const psiLibrary: IShellItem; grfMode: DWORD; const riid: TIID; out ppv): HResult; var plib: IShellLibrary; begin Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IID_IShellLibrary, plib); if Succeeded(Result) then begin Result := plib.LoadLibraryFromItem(psiLibrary, grfMode); if Succeeded(Result) then Result := plib.QueryInterface(riid, ppv); end; end; function GetShellLibraryforLibrary(const LibraryName: String; grfMode: DWORD; var ppv: IShellLibrary): Boolean; var SL: IShellLibrary; Enum: IEnumShellItems; Item: IShellItem; DisplayName: LPWSTR; hr: HRESULT; begin Result := False; ppv := nil; if FAILED(SHGetKnownFolderItem(FOLDERID_Libraries, 0, 0, IShellItem, PPointer(@Item)^) then Exit; hr := Item.BindToHandler(nil, BHID_EnumItems, IEnumShellItems, Enum); if FAILED(hr) then Exit; Item := nil; while Enum.Next(1, Item, nil) = S_OK do begin if FAILED(Item.GetDisplayName(SIGDN_NORMALDISPLAY, DisplayName)) then Exit; try if AnsiSameText(DisplayName, LibraryName) then begin Result := SUCCEEDED(My_SHLoadLibraryFromItem(Item, grfMode, IShellLibrary, ppv)); Break; end; finally CoTaskMemFree(DisplayName); end; Item := nil; end; end; function GetLibraryFileSystemFolders(const LibraryName: String; Folders: TStrings): Boolean; var SL: IShellLibrary; Arr: IShellItemArray; Enum: IEnumShellItems; Item: IShellItem; Path: LPWSTR; begin Result := False; if not GetShellLibraryforLibrary(LibraryName, STGM_READ, SL) then Exit; if FAILED(SL.GetFolders(LFF_FORCEFILESYSTEM, IShellItemArray, Arr)) then Exit; if FAILED(Arr.EnumItems(Enum)) then Exit; while Enum.Next(1, Item, nil) = S_OK then begin if FAILED(Item.GetDisplayName(SIGDN_FILESYSPATH, Path)) then Exit; try Folders.Add(Path); finally CoTaskMemFree(Path); end; Item := nil; end; Result := True; end;
。
var Folders: TStringList; begin Folders := TStringList.Create; try if GetLibraryFileSystemFolders('MyLibrary', Folders) then begin //... end; finally Folders.Free; end; end;
我刚刚在Marco Cantu的Mastering Delphi书籍的源代码库中找到了一个Delphi 2010的例子,它显示了一个在库中获取位置的方法。
到版本库的链接在这里: http : //code.marcocantu.com/p/marcodelphibooks/source/tree/HEAD/
在chapter 05 (Win7Libraries)
, chapter 05 (Win7Libraries)
就是示例源码。
该演示中使用的方法基本上是已经提到的Windows API的使用,演示确认库文件确实是XML格式。
此外,我发现以下信息非常有用: