如何读/写 Windows 7 库位置? [英] How to Read/Write Windows 7 Library Locations?

查看:20
本文介绍了如何读/写 Windows 7 库位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介

在 Windows 7 中,您有一些特殊的文件夹,用于存放文档、图片和音乐等,称为库.

如果您不知道它们,基本上每个库文件夹都可以包含位置(路径),它们基本上是每个库的快捷方式.

一些例子:

文档(库)

  • E:PersonalDocuments (位置)
  • F:BackupsDocuments (位置)

音乐(图书馆)

  • E:MediaMusicAlbums (位置)
  • E:MediaMusicSingles (位置)

图片(库)

  • E:MediaPhotos (位置)

当您从 Windows 资源管理器或开始"菜单单击这些库文件夹中的任何一个时,Windows 资源管理器将显示该库中定义的位置.

任务

我需要做的是读取每种图书馆类型的位置,并能够用我自己的位置写回(更新)图书馆.我发现库存储在用户 AppData 文件夹中,如下所示:

C:UsersSOMEUSERAppDataRoamingMicrosoftWindowsLibraries

这些库是这种文件类型:库 (.library-ms) - 如果您右键单击一个并选择属性,库选项卡,您可以看到与该库关联的库位置.>

我没有看到提取这些并将它们放入例如 TStringList 以在 Delphi 中进行编辑的方法.我想知道这些库位置是否真的存储在 Windows 注册表中,所以通过谷歌的一些研究,我找到了这些路径:

  • HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerShell 文件夹
  • HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell 文件夹

但同样,我没有看到图书馆位置的实际列表.

那么,如何在 Delphi 中读取库文件中的位置列表,将它们添加到列表框或 TStringList,编辑条目然后写回更改?能够提取库位置路径将是一个开始.

我只是有一种感觉,这将是那些似乎找不到简单答案的问题之一!

解决方案

使用 SHLoadLibraryFrom...() 函数之一,如 SHLoadLibraryFromKnownFolder(),得到一个IShellLibrary接口,然后你可以使用它的方法来枚举和操作Library,比如IShellLibrary::GetFolders()IShellLibrary::AddFolder()IShellLibrary::RemoveFolder()

更新:例如:

使用...,ActiveX,已知文件夹,ShlObj;//SHLoadLibraryFrom...() 函数在 Win32 SDK 中内联实现//shobjidl.h 头文件,所以你必须在你的//如果您使用的不是已经实现的 Delphi 版本,请编写代码//它们在 RTL 的 ShlObj.pas 单元中为您...//SHLoadLibraryFromKnownFolder() 在 ShlObj.pas 中定义错误!!!见 QC #109306函数 My_SHLoadLibraryFromKnownFolder(const kfidLibrary: TGUID; grfMode: DWORD; riid: TIID; out ppv): HRESULT;无功plib: IShellLibrary;开始结果 := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IShellLibrary, plib);如果成功(结果)那么开始结果:= plib.LoadLibraryFromKnownFolder(kfidLibrary, grfMode);如果成功(结果)那么结果:= plib.QueryInterface(riid, ppv);结尾;结尾;函数 GetLibraryFileSystemFolders(FolderID: TGUID; Folders: TStrings): Boolean;无功SL:IShellLibrary;到达:IShellItemArray;枚举:IEnumShellItems;项目:IShellItem;路径:LPWSTR;开始结果:=假;如果失败(My_SHLoadLibraryFromKnownFolder(FolderID, STGM_READ, IShellLibrary, SL)) 然后出口;如果失败(SL.GetFolders(LFF_FORCEFILESYSTEM, IShellItemArray, Arr)) 然后出口;如果 FAILED(Arr.EnumItems(Enum)) 然后出口;而 Enum.Next(1, Item, nil) = S_OK 然后开始如果失败(Item.GetDisplayName(SIGDN_FILESYSPATH, Path)) 那么出口;尝试Folders.Add(Path);最后CoTaskMemFree(路径);结尾;项目:= 零;结尾;结果:=真;结尾;

.

var文件夹:TStringList;开始文件夹:= TStringList.Create;尝试如果 GetLibraryFileSystemFolders(FOLDERID_DocumentsLibrary, Folders) 那么开始//...结尾;最后文件夹.免费;结尾;结尾;

更新:SHLoadLibraryFromKnownFolder() 仅适用于定义了 KNOWNFOLDERID 值的 Microsoft 定义的库.如果要访问自定义库,则必须使用稍微修改的方法来获取IShellLibrary 接口,例如:

//SHLoadLibraryFromItem() 在 ShlObj.pas 中定义错误!!!见 QC #109306函数 My_SHLoadLibraryFromItem(const psiLibrary: IShellItem; grfMode: DWORD; const riid: TIID; out ppv): HResult;无功plib: IShellLibrary;开始结果 := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IID_IShellLibrary, plib);如果成功(结果)然后开始结果:= plib.LoadLibraryFromItem(psiLibrary, grfMode);如果成功(结果)然后结果:= plib.QueryInterface(riid, ppv);结尾;结尾;函数 GetShellLibraryforLibrary(const LibraryName: String; grfMode: DWORD; var ppv: IShellLibrary): Boolean;无功SL:IShellLibrary;枚举:IEnumShellItems;项目:IShellItem;显示名称:LPWSTR;小时:HRESULT;开始结果:=假;ppv := 零;如果失败(SHGetKnownFolderItem(FOLDERID_Libraries, 0, 0, IShellItem, PPointer(@Item)^) 那么出口;hr := Item.BindToHandler(nil, BHID_EnumItems, IEnumShellItems, Enum);如果失败(小时)那么出口;项目:= 零;而 Enum.Next(1, Item, nil) = S_OK 做开始如果 FAILED(Item.GetDisplayName(SIGDN_NORMALDISPLAY, DisplayName)) 然后出口;尝试如果 AnsiSameText(DisplayName, LibraryName) 那么开始结果 := SUCCEEDED(My_SHLoadLibraryFromItem(Item, grfMode, IShellLibrary, ppv));休息;结尾;最后CoTaskMemFree(DisplayName);结尾;项目:= 零;结尾;结尾;函数 GetLibraryFileSystemFolders(const LibraryName: String; Folders: TStrings): Boolean;无功SL:IShellLibrary;到达:IShellItemArray;枚举:IEnumShellItems;项目:IShellItem;路径:LPWSTR;开始结果:=假;如果不是 GetShellLibraryforLibrary(LibraryName, STGM_READ, SL) 然后出口;如果失败(SL.GetFolders(LFF_FORCEFILESYSTEM, IShellItemArray, Arr)) 然后出口;如果 FAILED(Arr.EnumItems(Enum)) 然后出口;而 Enum.Next(1, Item, nil) = S_OK 然后开始如果失败(Item.GetDisplayName(SIGDN_FILESYSPATH, Path)) 那么出口;尝试Folders.Add(Path);最后CoTaskMemFree(路径);结尾;项目:= 零;结尾;结果:=真;结尾;

.

var文件夹:TStringList;开始文件夹:= TStringList.Create;尝试如果 GetLibraryFileSystemFolders('MyLibrary', Folders) 那么开始//...结尾;最后文件夹.免费;结尾;结尾;

Intro

In Windows 7 you have some special folders for documents, pictures and music etc called Libraries.

If you are not aware of them, basically each Library folder can contain Locations (paths) which are basically shortcuts for each Library.

Some examples:

Documents (Library)

  • E:PersonalDocuments (Location)
  • F:BackupsDocuments (Location)

Music (Library)

  • E:MediaMusicAlbums (Location)
  • E:MediaMusicSingles (Location)

Pictures (Library)

  • E:MediaPhotos (Location)

When you click any of these Library folders from Windows Explorer or Start menu, Windows Explorer will show with the Locations defined inside that Library.

Task

What I need to be able to do is read the Locations for each Library type, and be able to write back (update) the Library with my own Locations. I have found that the Libraries are stored in the user AppData folder like this:

C:UsersSOMEUSERAppDataRoamingMicrosoftWindowsLibraries

These Libraries are this file type: Library (.library-ms) - if you right click on one and select properties, Library tab you can see the Library locations associated with that Library.

I don't see a way of extracting these and putting them for example into a TStringList for editing in Delphi. I wondered if these Library Locations were actually stored in the Windows Registry so with some research from Google I found these paths:

  • HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerShell Folders
  • HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders

But again, I don't see the actual list of Library Locations.

So, how can I read the list of Locations inside a Library file in Delphi, add them to a Listbox or TStringList, edit the entries and then write back the changes? Just been able to extract the Library Location paths would be a start.

I just have a feeling this is going to be one of those questions that has a simple answer I cannot seem to find!

解决方案

Use one of the SHLoadLibraryFrom...() functions, like SHLoadLibraryFromKnownFolder(), to get an IShellLibrary interface, then you can use its methods to enumerate and manipulate the Library, such as IShellLibrary::GetFolders(), IShellLibrary::AddFolder(), IShellLibrary::RemoveFolder(), etc.

Update: For example:

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;

Update: SHLoadLibraryFromKnownFolder() only works for Microsoft-defined Libraries that have KNOWNFOLDERID values defined. If you want to access custom Libraries, you have to use a slightly modified approach to obtaining the IShellLibrary interface, eg:

// 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;

这篇关于如何读/写 Windows 7 库位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆