• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 623
  • Last Modified:

How to check if the recycle bin is empty in DElphi.

I am using Delphi 2010 on a Win 7 64 bit machine and I need to check if the recycle bin is empty. I picked up the following from the web

function RecycleBinIsEmpty: Boolean;
const
  CLSID_IRecycleBin: TGUID = (D1: $645FF040; D2: $5081; D3: $101B;
    D4: ($9F, $08, $00, $AA, $00, $2F, $95, $4E));
var
  EnumIDList: IEnumIDList;
  FileItemIDList: PItemIDList;
  ItemCount: ULONG;
  RecycleBin: IShellFolder;
begin
  CoInitialize(nil);
  OleCheck(CoCreateInstance(CLSID_IRecycleBin, nil, CLSCTX_INPROC_SERVER or
    CLSCTX_LOCAL_SERVER, IID_IShellFolder, RecycleBin));
  RecycleBin.EnumObjects(0,
    SHCONTF_FOLDERS or
    SHCONTF_NONFOLDERS or
    SHCONTF_INCLUDEHIDDEN,
    EnumIDList);
  Result := EnumIDList.Next(1, FileItemIDList, ItemCount) <> NOERROR;
  CoUninitialize;
end;

but no matter what the result always indicates the Recycle Bin is empty even when I have checked that it is not empty. I even tried checking the number of items in the recycle bin using

var
  rbinfo: SHQUERYRBINFO;
  Retval: Integer;
begin
  rbinfo.cbSize := SizeOf(rbinfo);

  Retval := SHQueryRecycleBin('',@rbinfo);

But Retval always ends up as 0.

Has anyone got any idea what is going wrong?
0
Rodbach
Asked:
Rodbach
  • 2
1 Solution
 
tailoreddigitalCommented:
I know nothing about Delphi, but in looking at code from the web, your code has a slight difference when compared to the code from the web,

YOUR CODE
Result := EnumIDList.Next(1, FileItemIDList, ItemCount) <> NOERROR;
                                                                                                                    ^^
                                                                                                                    ||

FROM THE WEB
Result := EnumIDList.Next(1, FileItemIDList, ItemCount)  NOERROR;


I don't know if it makes any difference, but i thought i'd point it out.
0
 
rinfoCommented:
try SHQueryRecycleBin in shell32.

function RecycleBinInfo(const Drive: Char; out BinSize, FileCount: Int64):
  Boolean;
type
  // structure passed to SHQueryRecycleBin to get information about recyle bin
  TSHQueryRBInfo = packed record
    cbSize: Integer;    // size of structure
    i64Size: Int64;     // size of recycle bin
    i64NumItems: Int64; // number of items in recycle bin.
  end;
  PSHQueryRBInfo = ^TSHQueryRBInfo;
  // function prototype for SHQueryRecycleBin (prototypes Unicode version when
  // PChar = PWideChar and ANSI version when PChar = PAnsiChar
  TSHQueryRecycleBin = function(RootPath: PChar; Query: PSHQueryRBInfo): 
    Integer; stdcall;
const
  {$IFDEF UNICODE}
  cSHQueryRecycleBin = 'SHQueryRecycleBinW';  // Unicode SHQueryRecycleBin fn
  {$ELSE}
  cSHQueryRecycleBin = 'SHQueryRecycleBinA';  // ANSI SHQueryRecycleBin fn
  {$ENDIF}
  cShell32 = 'shell32.dll';                   // SHQueryRecycleBin's DLL
var
  SHQueryRecycleBin: TSHQueryRecycleBin;  // reference to SHQueryRecycleBin fn
  Shell32: Windows.THandle;               // handle to shel32.dll
  SHQueryRBInfo: TSHQueryRBInfo;          // structure receive recyle bin info
  RootDir: string;                        // directory we are getting info for
  PRootDir: PChar;                        // pointer to root dir or nil
begin
  // Intialise to assume failure
  Result := False;
  BinSize := 0;
  FileCount := 0;
  // Attempt to load required SHQueryRecycleBin function from DLL
  Shell32 := SysUtils.SafeLoadLibrary(cShell32);
  if Shell32 <> 0 then
  begin
    @SHQueryRecycleBin := Windows.GetProcAddress(Shell32, cSHQueryRecycleBin);
    if Assigned(@SHQueryRecycleBin) then
    begin
      // Set structure size before calling SHQueryRecycleBin
      SHQueryRBInfo.cbSize := SizeOf(SHQueryRBInfo);
      // Create pointer to required drive (nul to get all drives)
      {$IFDEF UNICODE}
      if SysUtils.CharInSet(UpCase(Drive), ['A'..'Z']) then
      {$ELSE}
      if UpCase(Drive) in ['A'..'Z'] then
      {$ENDIF}
      begin
        RootDir := UpCase(Drive) + ':\';
        PRootDir := PChar(RootDir);
      end
      else
        PRootDir := nil;
      // Get recycle info
      Result := SHQueryRecycleBin(PRootDir, @SHQueryRBInfo) = 0;
      if Result then
      begin
        // Success: pass info back through params
        BinSize := SHQueryRBInfo.i64Size;
        FileCount := SHQueryRBInfo.i64NumItems;
      end;
    end;
  end;
end;

Open in new window

0
 
rinfoCommented:
This is the complete example i tried and tested.
procedure TForm1.Button1Click(Sender: TObject);
var Binsize,FileCount:Int64;
begin
  RecycleBinInfo(  'C',BinSize, FileCount);
end;

function TForm1.RecycleBinInfo(const Drive: Char; out BinSize, FileCount: Int64):
  Boolean;
type
  // structure passed to SHQueryRecycleBin to get information about recyle bin
  TSHQueryRBInfo = packed record
    cbSize: Integer;    // size of structure
    i64Size: Int64;     // size of recycle bin
    i64NumItems: Int64; // number of items in recycle bin.
  end;
  PSHQueryRBInfo = ^TSHQueryRBInfo;
  // function prototype for SHQueryRecycleBin (prototypes Unicode version when
  // PChar = PWideChar and ANSI version when PChar = PAnsiChar
  TSHQueryRecycleBin = function(RootPath: PChar; Query: PSHQueryRBInfo):
    Integer; stdcall;
const
  {$IFDEF UNICODE}
  cSHQueryRecycleBin = 'SHQueryRecycleBinW';  // Unicode SHQueryRecycleBin fn
  {$ELSE}
  cSHQueryRecycleBin = 'SHQueryRecycleBinA';  // ANSI SHQueryRecycleBin fn
  {$ENDIF}
  cShell32 = 'shell32.dll';                   // SHQueryRecycleBin's DLL
var
  SHQueryRecycleBin: TSHQueryRecycleBin;  // reference to SHQueryRecycleBin fn
  Shell32: Windows.THandle;               // handle to shel32.dll
  SHQueryRBInfo: TSHQueryRBInfo;          // structure receive recyle bin info
  RootDir: string;                        // directory we are getting info for
  PRootDir: PChar;                        // pointer to root dir or nil
begin
  // Intialise to assume failure
  Result := False;
  BinSize := 0;
  FileCount := 0;
  // Attempt to load required SHQueryRecycleBin function from DLL
  Shell32 := SysUtils.SafeLoadLibrary(cShell32);
  if Shell32 <> 0 then
  begin
    @SHQueryRecycleBin := Windows.GetProcAddress(Shell32, cSHQueryRecycleBin);
    if Assigned(@SHQueryRecycleBin) then
    begin
      // Set structure size before calling SHQueryRecycleBin
      SHQueryRBInfo.cbSize := SizeOf(SHQueryRBInfo);
      // Create pointer to required drive (nul to get all drives)
      {$IFDEF UNICODE}
      if SysUtils.CharInSet(UpCase(Drive), ['A'..'Z']) then
      {$ELSE}
      if UpCase(Drive) in ['A'..'Z'] then
      {$ENDIF}
      begin
        RootDir := UpCase(Drive) + ':\';
        PRootDir := PChar(RootDir);
      end
      else
        PRootDir := nil;
      // Get recycle info
      Result := SHQueryRecycleBin(PRootDir, @SHQueryRBInfo) = 0;
      if Result then
      begin
        // Success: pass info back through params
        BinSize := SHQueryRBInfo.i64Size;
        FileCount := SHQueryRBInfo.i64NumItems;
        showMessage(intToStr(FileCount));
      end;
    end;
  end;
end;

Open in new window

0
 
RodbachAuthor Commented:
tailoreddigital - the web code is wrong that line needs the '<>' in order to compile. The right hand side of the assignment needs to evaluate to a Boolean value. But well spotted.

rinfo - your example works perfectly and I have awarded you the points. many thanks
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now