7

イントロ

Windows 7には、ライブラリと呼ばれるドキュメント、画像、音楽などの特別なフォルダがいくつかあります。

それらに気付いていない場合、基本的に各ライブラリフォルダには、基本的に各ライブラリのショートカットである場所(パス)を含めることができます。

いくつかの例:

Documents (Library)

  • E:\ Personal \ Documents(Location)
  • F:\ Backups \ Documents(Location)

Music (Library)

  • E:\ Media \ Music \ Albums(Location)
  • E:\ Media \ Music \ Singles(Location)

Pictures (Library)

  • E:\ Media \ Photos(Location)

Windowsエクスプローラーまたは[スタート]メニューからこれらのライブラリフォルダーのいずれかをクリックすると、Windowsエクスプローラーにそのライブラリ内で定義された場所が表示されます。

タスク

私ができる必要があるのは、各ライブラリタイプの場所を読み取り、自分の場所でライブラリを書き戻す(更新する)ことができるようにすることです。ライブラリは次のようにユーザーのAppDataフォルダーに保存されていることがわかりました。

C:\Users\SOMEUSER\AppData\Roaming\Microsoft\Windows\Libraries

これらのライブラリは次のファイルタイプです。ライブラリ(.library-ms) -いずれかを右クリックしてプロパティを選択すると、[ライブラリ]タブにそのライブラリに関連付けられているライブラリの場所が表示されます。

これらを抽出して、たとえばDelphiで編集するためにTStringListに入れる方法がわかりません。これらのライブラリの場所が実際にWindowsレジストリに保存されているのかどうか疑問に思ったので、Googleの調査で、次のパスを見つけました。

  • HKEY_CURRENT_USER \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ Shell Folders
  • HKEY_CURRENT_USER \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ User Shell Folders

しかし、繰り返しになりますが、ライブラリの場所の実際のリストは表示されません。

では、Delphiでライブラリファイル内の場所のリストを読み取り、それらをリストボックスまたはTStringListに追加し、エントリを編集してから、変更を書き戻すにはどうすればよいですか?ライブラリの場所のパスを抽出できただけで始まります。

私はこれが私が見つけることができないように思われる簡単な答えを持っているそれらの質問の1つになるだろうと感じています!

4

2 に答える 2

6

SHLoadLibraryFrom...()、などの関数の1つを使用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()ているMicrosoft定義のライブラリでのみ機能します。KNOWNFOLDERIDカスタムライブラリにアクセスする場合は、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;
于 2012-09-18T22:06:39.007 に答える
1

マルコカントゥのMasteringDelphiの本のソースコードリポジトリで、ライブラリ内の場所を取得する方法を示すDelphi2010の例を見つけました。

リポジトリへのリンクはここにあります:http://code.marcocantu.com/p/marcodelphibooks/source/tree/HEAD/

delphi2010handbookchapter 05 (Win7Libraries)ソースの例です。

そのデモで使用される方法は、基本的にはすでに述べたWindows APIの使用であり、デモはライブラリファイルが実際にXML形式であることを確認します。


さらに、次の情報が非常に役立ちます。

  • SHAddFolderPathToLibrary-フォルダーをライブラリに追加します。
  • SHCreateLibraryIShellLibrary-オブジェクトを作成します。
  • SHLoadLibraryFromItem -IShellLibraryを作成し、指定されたライブラリ定義ファイルからオブジェクトにロードします。
  • SHLoadLibraryFromKnownFolder-指定されたKNOWNFOLDERIDのIShellLibraryオブジェクトを作成してロードします。
  • SHLoadLibraryFromParsingName-指定されたパスのIShellLibraryオブジェクトを作成してロードします。
  • SHRemoveFolderPathFromLibrary-ライブラリからフォルダを削除します。
  • SHResolveFolderPathInLibrary-移動または名前変更されたライブラリフォルダーのターゲットの場所を解決しようとします。
  • SHResolveLibrary-ライブラリの場所を見つけようとします。
  • SHSaveLibraryInFolderPath -IShellLibraryオブジェクトをディスクに保存します。
  • SHShowManageLibraryUI-ライブラリ管理ダイアログを表示します。これにより、ユーザーはライブラリフォルダとデフォルトの保存場所を管理できます。
于 2012-09-19T11:28:13.410 に答える