[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 451
  • Last Modified:

Delete old files from recycle bin

I would like to write a program to delete old files from recycle bin without emptying the recycle bin.
For example those files that were deleted into the recycle bin more than one week ago. If I didn't miss them within the last week, I don't need them. The program could start every day.
Does anyone know how to access the files in the recycle bin?
0
rakoru
Asked:
rakoru
  • 2
  • 2
  • 2
  • +1
1 Solution
 
sun4sundayCommented:
You can access the recycle bin using SHEmptyRecycleBin

Check this answered solution to empty recycle bin, but not with specific date range
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_10205254.html

sun4sunday
0
 
saravananvgCommented:
Sir,

  You could use the following code to empty recycle bin

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics,
  ShellApi,Controls, Forms, Dialogs,StdCtrls, ExtCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

function SHEmptyRecycleBin
 (Wnd:HWnd; LPCTSTR:PChar; DWORD:Word):Integer; stdcall;

const
SHERB_NOCONFIRMATION = $00000001;
SHERB_NOPROGRESSUI   = $00000002;
SHERB_NOSOUND        = $00000004;

implementation

{$R *.DFM}

function SHEmptyRecycleBin; external 'SHELL32.DLL' name 'SHEmptyRecycleBinA';

procedure TForm1.Button1Click(Sender: TObject);
begin
SHEmptyRecycleBin(self.handle,'',SHERB_NOCONFIRMATION);
end;

end.

with regards,
padmaja.
0
 
saravananvgCommented:
Hello Sir,

  You could open the recycle bin programatically as follows.

uses
  ShlObj, ShellAPI, ... ;
Place a TButton named "OpenBinButton" on a form, handle its OnClick event as:

procedure TRecycleBinForm.OpenBinButtonClick(Sender: TObject) ;
var
   recycleBinPIDL: PItemIDList;
   execInfo: TShellExecuteInfo;
begin
   SHGetSpecialFolderLocation(Handle, CSIDL_BITBUCKET, recycleBinPIDL) ;
   with execInfo do
   begin
     cbSize := Sizeof(execInfo) ;
     fMask := SEE_MASK_IDLIST;
     Wnd := Handle;
     lpVerb := nil;
     lpFile := nil;
     lpParameters := nil;
     lpDirectory := nil;
     nShow := SW_SHOWNORMAL;
     hInstApp:=0;
     lpIDList := recycleBinPIDL;
   end;
   ShellExecuteEx(@execInfo) ;
end;

with regards,
padmaja.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
rakoruAuthor Commented:
Hello,
thanks for your comments.
The problem is that it will be necessary to enumerate the files in the recycle bin.
(like "FindFirst" and "FindNext")
The program will have to check each file, decide wether it is "old" or not
and delete exclusively the "old" files.

rakoru
0
 
Russell LibbySoftware Engineer, Advisory Commented:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComObj, ActiveX, ShlObj, ShellApi, StdCtrls;

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

type
  PSHColInfo        =  ^SHColInfo;
  SHColInfo         =  record
     justify:       Integer;
     width:         Integer;
     text:          STRRET;
  end;

const
  IID_IShellFolder2:TGUID =  (D1:$93F2F68C; D2:$1D1B; D3:$11D3; D4:($A3,$0E,$00,$C0,$4F,$79,$AB,$D1));

const
  SID_IShellFolder2       =  '{93F2F68C-1D1B-11D3-A30E-00C04F79ABD1}';
  SID_IEnumExtraSearch    =  '{0E700BE1-9DB6-11D1-A1CE-00C04FD75D13}';

type
  PShellDetails        =  ^TShellDetails;
  _SHELLDETAILS        =  record
     fmt,
     cxChar:           Integer;
     str:              STRRET;
  end;
  TShellDetails        =  _SHELLDETAILS;
  SHELLDETAILS         =  _SHELLDETAILS;

type
  PExtraSearch         =  ^TExtraSearch;
  TExtraSearch         =  record
     guidSearch:       TGUID;
     wszFriendlyName,
     wszMenuText:      Array [0..79] of WideChar;
     wszHelpText:      Array [0..MAX_PATH] of WideChar;
     wszUrl:           Array [0..2047] of WideChar;
     wszIcon,
     wszGreyIcon,
     wszClrIcon:       Array [0..MAX_PATH+10] of WideChar;
  end;

type
  IEnumExtraSearch     =  interface(IUnknown)
     [SID_IEnumExtraSearch]
     function          Next(celt: ULONG; out rgelt: PExtraSearch; out pceltFetched: ULONG): HResult; stdcall;
     function          Skip(celt: ULONG): HResult; stdcall;
     function          Reset: HResult; stdcall;
     function          Clone(out ppEnum: IEnumExtraSearch): HResult; stdcall;
  end;

const
  // IShellFolder2.GetDefaultColumnState Values
  SHCOLSTATE_TYPE_STR     = $00000001;
  SHCOLSTATE_TYPE_INT     = $00000002;
  SHCOLSTATE_TYPE_DATE    = $00000003;
  SHCOLSTATE_TYPEMASK     = $0000000F;
  SHCOLSTATE_ONBYDEFAULT  = $00000010;   // should on by default in details view
  SHCOLSTATE_SLOW         = $00000020;   // will be slow to compute; do on a background thread
  SHCOLSTATE_EXTENDED     = $00000040;   // provided by a handler; not the folder
  SHCOLSTATE_SECONDARYUI  = $00000080;   // not displayed in context menu; but listed in the "More..." dialog
  SHCOLSTATE_HIDDEN       = $00000100;   // not displayed in the UI

type
  PShColumnID       =  ^TShColumnID;
  SHCOLUMNID        = record
     fmtid:         TGUID;
     pid:           DWORD;
  end;
  TShColumnID       =  SHCOLUMNID;

type
  IShellFolder2     =  interface(IShellFolder)
     [SID_IShellFolder2]
     function       GetDefaultSearchGUID(out pguid: TGUID): HResult; stdcall;
     function       EnumSearches(out ppEnum: IEnumExtraSearch): HResult; stdcall;
     function       GetDefaultColumn(dwRes: DWORD; var pSort: ULONG; var pDisplay: ULONG): HResult; stdcall;
     function       GetDefaultColumnState(iColumn: UINT; var pcsFlags: DWORD): HResult; stdcall;
     function       GetDetailsEx(pidl: PItemIDList; const pscid: SHCOLUMNID; pv: POleVariant): HResult; stdcall;
     function       GetDetailsOf(pidl: PItemIDList; iColumn: UINT; var psd: TShellDetails): HResult; stdcall;
     function       MapNameToSCID(pwszName: LPCWSTR; var pscid: TShColumnID): HResult; stdcall;
  end;

var
  Form1:            TForm1;

implementation
{$R *.DFM}

function RecycleBinCleanup(DateDeleted: TDateTime): Integer;
var  pvDesktop:        IShellFolder;
     pvFolder2:        IShellFolder2;
     pvEnumList:       IEnumIDList;
     pvMalloc:         IMalloc;
     pidlRecycleBin:   PItemIDList;
     pidlItem:         PItemIDList;
     lpDetails:        TShellDetails;
     lpOperation:      TSHFileOpStruct;
     szColumn:         String;
     szDate:           String;
     dtDeleted:        TDateTime;
     hrReturn:         HRESULT;
     cbCount:          ULONG;
     dwIndex:          UINT;
begin

  // Default result (no objects deleted)
  result:=0;

  // Get malloc
  if (SHGetMalloc(pvMalloc) = S_OK) then
  begin
     // Get desktop folder
     if (SHGetDesktopFolder(pvDesktop) = S_OK) then
     begin
        // Get recycle bin pidl
        if (SHGetSpecialFolderLocation(Application.Handle, CSIDL_BITBUCKET, pidlRecycleBin) = S_OK) then
        begin
           // Bind to folder 2 interface
           if (pvDesktop.BindToObject(pidlRecycleBin, nil, IID_IShellFolder2, pvFolder2) = S_OK) then
           begin
              // Set loop enumerator
              dwIndex:=0;
              // Set default column name
              szColumn:=EmptyStr;
              // Loop columns
              repeat
                 // Get column info
                 hrReturn:=pvFolder2.GetDetailsOf(nil, dwIndex, lpDetails);
                 // Check result
                 if (hrReturn = S_OK) then
                 begin
                    // Get column name
                    case lpDetails.str.uType of
                       STRRET_CSTR    :  SetString(szColumn, lpDetails.str.cStr, lStrLen(lpDetails.str.cStr));
                       STRRET_OFFSET  :  szColumn:=EmptyStr;
                       STRRET_WSTR    :
                       begin
                          szColumn:=lpDetails.str.pOleStr;
                          pvMalloc.Free(lpDetails.str.pOleStr);
                       end;
                    else
                       szColumn:=EmptyStr;
                    end;
                    // Check column name
                    if (CompareText(szColumn, 'Date Deleted') = 0) then
                       // We have the column
                       break
                    else
                       // Increment the column index
                       Inc(dwIndex);
                 end;
              until (hrReturn <> S_OK);
              // Check result status
              if (hrReturn = S_OK) then
              begin
                 // Get enumerator
                 if (pvFolder2.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, pvEnumList) = S_OK) then
                 begin
                    // Enumerate items
                    while (pvEnumList.Next(1, pidlItem, cbCount) = S_OK) do
                    begin
                       // Get the date deleted for the item
                       if (pvFolder2.GetDetailsOf(pidlItem, dwIndex, lpDetails) = S_OK) then
                       begin
                          case lpDetails.str.uType of
                             STRRET_CSTR    :  SetString(szDate, lpDetails.str.cStr, lStrLen(lpDetails.str.cStr));
                             STRRET_OFFSET  :  szDate:=DateTimeToStr(Now);
                             STRRET_WSTR    :
                             begin
                                szDate:=lpDetails.str.pOleStr;
                                pvMalloc.Free(lpDetails.str.pOleStr);
                             end;
                          else
                             szDate:=DateTimeToStr(Now);
                          end;
                          // Convert string to date time
                          try
                             dtDeleted:=StrToDateTime(szDate);
                             // Compare the date time to passed date time
                             if (dtDeleted <= DateDeleted) then
                             begin
                                // Get file name
                                if (pvFolder2.GetDisplayNameOf(pidlItem, SHGDN_FORPARSING, lpDetails.str) = S_OK) then
                                begin
                                   case lpDetails.str.uType of
                                      STRRET_CSTR    :  SetString(szDate, lpDetails.str.cStr, lStrLen(lpDetails.str.cStr));
                                      STRRET_OFFSET  :  szDate:=EmptyStr;
                                      STRRET_WSTR    :
                                      begin
                                         szDate:=lpDetails.str.pOleStr;
                                         pvMalloc.Free(lpDetails.str.pOleStr);
                                      end;
                                   else
                                      szDate:=EmptyStr;
                                   end;
                                   // Append null to name
                                   szDate:=szDate+#0;
                                   // Clear structure
                                   FillChar(lpOperation, SizeOf(lpOperation), 0);
                                   // Set operation information
                                   lpOperation.Wnd:=Application.Handle;
                                   lpOperation.wFunc:=FO_DELETE;
                                   lpOperation.pFrom:=Pointer(szDate);
                                   lpOperation.fFlags:=FOF_NOCONFIRMATION or FOF_SILENT;
                                   // Delete the file
                                   SHFileOperation(lpOperation);
                                   // Update the number of objects deleted
                                   Inc(result);
                                end;
                             end;
                          except
                             // Eat the exception
                          end;
                       end;
                       // Free memory
                       CoTaskMemFree(pidlItem);
                    end;
                    // Release interface
                    pvEnumList:=nil;
                 end;
              end;
              // Release interface
              pvFolder2:=nil;
           end;
           // Free memory
           pvMalloc.Free(pidlRecycleBin);
        end;
        // Release interface
        pvDesktop:=nil;
     end;
     // Release interface
     pvMalloc:=nil;
  end;

end;

--- example usage ---

procedure TForm1.Button1Click(Sender: TObject);
begin

  // Cleanup files that were deleted 7 days ago
  RecycleBinCleanup(Now-7);
 
end;

end.



Regards,
Russell
0
 
rakoruAuthor Commented:
Hello rllibby,

this has really been an excellent answer!
Thank you very much.
The only thing I had to adjust was the column name
(near: "Check column name").
After replacing 'Date Deleted' by the german 'Löschdatum' the program worked wonderful.

rakoru
0
 
Russell LibbySoftware Engineer, Advisory Commented:

Your very welcome, and sorry about the column name (there is no generic mechanism to handle this unfortunately).

Regards,
Russell
0
 
sun4sundayCommented:
Russell

Excellent answer. You are great..

sun4sunday
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

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