Jak pobrać nazwy plików w koszu

reichel

Zazwyczaj pobieranie listy plików robi się z wykorzystaniem funkcji FindFirst i FindNext. W przypadku kosza jednak dają one dziwne nazwy (w stylu Dd1.html dla jakiegoś pliku html). Z pomocą przychodzi interfejs ISHellFolder oraz funkcja GetDisplayNameOf. Dzięki temu możemy poznać prawdziwą nazwę pliku (przykład poniżej).

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses ShlObj, ShellAPI, ActiveX;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 hr:HRESULT;
 pMalloc: IMalloc;
 SFRecycleBin,SFDesktop:IShellFolder;
 EnumIDList:IEnumIDList;
 pidl,RecycleBinIDList:PItemIDList;
 olePath:PWideChar;
 fetched:Cardinal;
 FD:WIN32_FIND_DATA;
 StrResult:TStrRet;
 ItemName:String;
begin
   hr := CoInitialize(nil);
   hr := SHGetMalloc(pMalloc);
   hr := SHGetDesktopFolder(SFDesktop);
   hr := SHGetSpecialFolderLocation(Handle, CSIDL_BITBUCKET, RecycleBinIDList);

   hr := SFDesktop.BindToObject(RecycleBinIDList, nil, IID_IShellFolder, SFRecycleBin);

   //wazne aby byly nonfolders
   hr := SFRecycleBin.EnumObjects(Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, EnumIDList);
   repeat
      hr := EnumIDList.Next(1, pidl, fetched);
      if (hr = NOERROR) then
      begin
         //pobieramy nazwe jaka mial plik
         SFRecycleBin.GetDisplayNameOf(pidl,SHGDN_NORMAL,StrResult);
         case StrResult.uType of
           0: begin
                ItemName := WideCharToString(StrResult.pOleStr);
                pMalloc.Free(StrResult.pOleStr);
              end;
           1: ItemName := PChar(pidl)+StrResult.uOffset;
           2: ItemName := StrResult.cStr;
         end;
         hr := SHGetDataFromIDList(SFRecycleBin, pidl, SHGDFIL_FINDDATA, @FD,  sizeof(WIN32_FIND_DATA));
         //nazwa pliku i przyjazna nazwa
         ListBox1.Items.Add(FD.cFileName + '  '+ ExtractFileName(ItemName));
         pMalloc.Free(pidl);
      end;

   until (hr <> NOERROR);

   EnumIDList := nil;
   SFRecycleBin := nil;
   SFDesktop := nil;
   pMalloc := nil;

  CoUninitialize();//wlasciwie jest w ktoryms z drugich uses unitow.
end;

end.

Na forme kładziemy Button i Listbox'a. W nim pojawia się najpierw dziwna nazwa a potem właściwa.

ps. Mozna jeszcze zainteresowac sie interfejsem IShellFolder2 (wiecej szczegółów).

ps2. Niestety interfejs (a przynajmniej tak zachowuje sie w windows) nie listuje plików wewnątrz folderów. Tu chyba pozostaje dłubanie w bazie danych kosza umieszczonej w pliku INFO2 (przynajmniej od Windows ME).

ps3. Co prawda wyglada na to, że w folderach usuniętych plik zachowują swoją nazwę orginalną. Tak więc po znależieniu folderów w koszu można wylistować pliki (normalnie) aby utworzyć drzewo.

0 komentarzy