介绍
在Windows 7中,您有一些特殊文件夹,用于文档,图片和音乐等,称为库.
如果您不了解它们,基本上每个Library文件夹都可以包含位置(路径),这些基本上是每个库的快捷方式.
一些例子:
Documents (Library)
(Location)(Location)Music (Library)
(Location)(Location)Pictures (Library)
(Location)从Windows资源管理器或"开始"菜单中单击任何这些库文件夹时,Windows资源管理器将显示该库中定义的位置.
任务
我需要做的是阅读每个库类型的位置,并能够使用我自己的位置回写(更新)库.我发现库存储在用户AppData文件夹中,如下所示:
C:\Users\SOMEUSER\AppData\Roaming\Microsoft\Windows\Libraries
这些库是此文件类型:库(.library-ms) - 如果右键单击其中一个并选择属性,则"库"选项卡可以看到与该库关联的库位置.
我没有看到提取这些并将它们放入TStringList以便在Delphi中进行编辑的方法.我想知道这些库位置是否实际存储在Windows注册表中,所以通过Google的一些研究我发现了这些路径:
但同样,我没有看到库位置的实际列表.
那么,如何在Delphi中读取库文件中的Locations列表,将它们添加到Listbox或TStringList,编辑条目然后写回更改?刚刚能够提取库位置路径将是一个开始.
我只是觉得这将是一个有一个我无法找到的简单答案的问题之一!
使用的一个SHLoadLibraryFrom...()功能,如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;
Run Code Online (Sandbox Code Playgroud)
.
var
Folders: TStringList;
begin
Folders := TStringList.Create;
try
if GetLibraryFileSystemFolders(FOLDERID_DocumentsLibrary, Folders) then
begin
//...
end;
finally
Folders.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
更新: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;
Run Code Online (Sandbox Code Playgroud)
.
var
Folders: TStringList;
begin
Folders := TStringList.Create;
try
if GetLibraryFileSystemFolders('MyLibrary', Folders) then
begin
//...
end;
finally
Folders.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)