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;