Author: Vimil Saju
How to restore files from the recycle bin and delete files present in the recycle
bin.
Answer:
To restore as well as delete file from the bin you need to make use of the
following functions.
1
2 function SHQueryRecycleBin(pszrtootpath: pchar; QUERYRBINFO: pshqueryrbinfo):
3 integer;
4 stdcall; external 'shell32' name 'SHQueryRecycleBinA';
5 //used to get the number of files in the bin.
6
7 function _FindFirstChangeNotification(lpPathName: PChar; bWatchSubtree: TWinBool;
8 dwNotifyFilter:
9 DWORD): THandle; stdcall; external kernel32 name 'FindFirstChangeNotificationA';
10 // used to notify the program when user has deleted a file
11
12 function SHEmptyRecycleBin(hwnd: thandle; pszRootPath: pchar; dwFlags: integer):
13 integer; stdcall; external 'shell32.dll' name 'SHEmptyRecycleBinA';
14 //This function empties the recycle bin.
In delphi the function FindFirstChangeNotification is already declared but in
Delphi 3 and above it does not work correctly.If the second parameter is true then
the function always returns an invalid handle.(visit
http://members.aye.net/~bstowers/delphi/bugs/ for more info).
So you need to redeclare the FindFirstChangeNotification function as shown below.
15 type
16 TWinBool = (winFalse, winTrue);
17
18 function _FindFirstChangeNotification(lpPathName: PChar; bWatchSubtree: TWinBool;
19 dwNotifyFilter:
20 DWORD): THandle; stdcall; external kernel32 name
21 'FindFirstChangeNotificationA';
The above function is used to refresh the list of files in the recyclebin when the
user deletes a file.
To use this function we have to first create a thread.This thread checks
continuosly checks whether any file was deleted and then refreshes the list of
deleted items.
For more information see delphi tips 'SHQUERYBINFO', 'SHemptyrecycleBin',
'Get the list of files from bin'.
Here is the code of the thread.
22 unit Unit2;
23
24 interface
25
26 uses
27 Classes, SysUtils, windows;
28
29 type
30 TFileChangeNotify = class(TThread)
31 private
32
33 protected
34 procedure Execute; override;
35 procedure filenotify; //refreshes the list when user has deleted a file.
36 end;
37 var
38 qh1: thandle;
39 implementation
40
41 uses
42 unit1;
43
44 procedure TFileChangeNotify.filenotify;
45 begin
46 form1.refreshlist;
47 end;
48
49 procedure TFileChangeNotify.Execute;
50 var
51 pdir: pchar;
52 st: integer;
53 tmp: boolean;
54 begin
55 pdir := 'C:\';
56 qh1 := 0;
57 qh1 := _FindFirstChangeNotification(pdir, Twinbool(1),
58 FILE_NOTIFY_CHANGE_LAST_WRITE);
59 while true do
60 begin
61 st := WaitForSingleObject(qh1, INFINITE);
62 if st = WAIT_OBJECT_0 then
63 begin
64 Synchronize(filenotify);
65 SHUpdateRecycleBinIcon;
66 end;
67 tmp := findnextchangenotification(qh1);
68 if tmp = false then
69 Terminate;
70 end;
71 end;
72
73 end.
You need to add a Tlistview control to your form, and add two columns to it.
Here is the code of main program.
74 unit Unit1;
75
76 interface
77
78 uses
79 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
80 StdCtrls, Menus, ComCtrls, unit2; {unit2 is the unit in which the thread resides}
81
82 const
83 SHERB_NOCONFIRMATION = $1;
84 const
85 SHERB_NOPROGRESSUI = $2;
86 const
87 SHERB_NOSOUND = $4;
88
89 type
90 TWinBool = (winFalse, winTrue);
91
92 type
93 Tfbuf = packed record
94 data: array[0..255] of char;
95 u1: array[0..3] of char;
96 recno: smallint;
97 u2: array[0..18] of char;
98 end;
99
100 type
101 SHQUERYRBINFO = packed record
102 cbSize: integer;
103 i64Size: int64;
104 i64NumItems: int64;
105 end;
106 pshqueryrbinfo = ^SHQUERYRBINFO;
107
108 function SHQueryRecycleBin(pszrtootpath: pchar; QUERYRBINFO: pshqueryrbinfo):
109 integer;
110 stdcall; external 'shell32' name 'SHQueryRecycleBinA';
111 function _FindFirstChangeNotification(lpPathName: PChar; bWatchSubtree: TWinBool;
112 dwNotifyFilter: DWORD): THandle; stdcall; external kernel32 name
113 'FindFirstChangeNotificationA';
114 function SHUpdateRecycleBinIcon: integer; stdcall; external 'shell32.dll';
115 function SHEmptyRecycleBin(hwnd: thandle; pszRootPath: pchar; dwFlags: integer):
116 integer; stdcall; external 'shell32.dll' name 'SHEmptyRecycleBinA';
117
118 type
119 TForm1 = class(TForm)
120 RBinList: TListView;
121 MainMenu1: TMainMenu;
122 file1: TMenuItem;
123 View1: TMenuItem;
124 Refresh1: TMenuItem;
125 Edit1: TMenuItem;
126 SelectAll1: TMenuItem;
127 Restore1: TMenuItem;
128 N1: TMenuItem;
129 Delete1: TMenuItem;
130 N2: TMenuItem;
131 Close1: TMenuItem;
132 InvertSelection1: TMenuItem;
133 procedure FormCreate(Sender: TObject);
134 procedure Refresh1Click(Sender: TObject);
135 procedure FormResize(Sender: TObject);
136 procedure file1Click(Sender: TObject);
137 procedure SelectAll1Click(Sender: TObject);
138 procedure InvertSelection1Click(Sender: TObject);
139 procedure Restore1Click(Sender: TObject);
140 procedure FormClose(Sender: TObject; var Action: TCloseAction);
141 procedure Close1Click(Sender: TObject);
142 procedure FormShow(Sender: TObject);
143 procedure Delete1Click(Sender: TObject);
144 private
145 { Private declarations }
146 public
147 qh: thandle;
148 procedure refreshlist;
149 function updateinfo(fname: string): boolean;
150 //Makes appropriate changes to the INFO2 file
151 //present in recycled folder.
152 procedure Restorefiles; //restores the selected files from the recycle bin.
153 procedure deletefiles; //deletes the selected files from the recycle bin.
154 end;
155
156 var
157 Form1: TForm1;
158 rbinfo: SHQUERYRBINFO;
159 reccount: integer;
160 fhandle: integer;
161 monitorthread: TFileChangeNotify;
162
163 implementation
164
165 {$R *.DFM}
166
167 procedure tform1.deletefiles;
168 var
169 i: integer;
170 sname: string;
171 dname: string;
172 begin
173 monitorthread.Suspend;
174 for i := 0 to rbinlist.Items.Count - 1 do
175 begin
176 if rbinlist.Items[i].Selected = true then
177 begin
178 sname := ExtractFileDrive(rbinlist.Items[i].SubItems[0]) + '\Recycled\DC' +
179 rbinlist.Items[i].SubItems[1] + ExtractFileExt(rbinlist.Items[i].caption);
180 dname := rbinlist.Items[i].SubItems[0] + rbinlist.Items[i].caption;
181 deleteFile(sname);
182 updateinfo(dname);
183 end;
184 end;
185 monitorthread.Resume;
186 end;
187
188 function tform1.updateinfo(fname: string): boolean;
189 var
190 rbuff: Tfbuf;
191 fread: integer;
192 tsize: integer;
193 aname: pchar;
194 ch: char;
195 begin
196 result := false;
197 ch := #0;
198 fhandle := fileopen('C:\recycled\info2', fmOpenReadWrite or fmShareDenyNone);
199 if fhandle > 0 then
200 begin
201 tsize := GetFileSize(fhandle, nil);
202 setfilepointer(fhandle, 20, nil, FILE_BEGIN);
203 fread := 20;
204 while (fread
205 begin
206 fread := fread + fileread(fhandle, rbuff, 280);
207 if rbuff.data[0] <> #0 then
208 begin
209 aname := pchar(@rbuff.data[0]);
210 if StrComp(aname, pchar(fname)) = 0 then
211 begin
212 setfilepointer(fhandle, -280, nil, FILE_CURRENT);
213 filewrite(fhandle, ch, 1);
214 result := true;
215 break;
216 end;
217 end;
218 end;
219 fileclose(fhandle);
220 end;
221 end;
222
223 procedure tform1.refreshlist;
224 var
225 rbuff: Tfbuf;
226 fread: integer;
227 tsize: integer;
228 aname: pchar;
229 fitem: tlistitem;
230 dname: pchar;
231 iconhandle: thandle;
232 tmp: word;
233 iconid: integer;
234 icon: ticon;
235 begin
236 monitorthread.Suspend;
237 zeromemory(@rbuff, sizeof(rbuff));
238 rbinlist.Items.Clear;
239 fhandle := fileopen('C:\recycled\info2', fmOpenRead);
240 if fhandle > 0 then
241 begin
242 tsize := GetFileSize(fhandle, nil);
243 setfilepointer(fhandle, 20, nil, FILE_BEGIN);
244 fread := 20;
245 while (fread
246 begin
247 fread := fread + fileread(fhandle, rbuff, 280);
248 if rbuff.data[0] <> #0 then
249 begin
250 aname := pchar(@rbuff.data[0]);
251 dname := pchar((ExtractFileDrive(aname) + '\Recycled\DC' + inttostr
252 (rbuff.recno) + extractfileext(aname)));
253 iconhandle := ExtractAssociatedIcon(HInstance, dname, tmp);
254 icon.Handle := iconhandle;
255 iconid := largeimagelist.AddIcon(icon);
256 fitem := rbinlist.Items.add;
257 fitem.ImageIndex := iconid;
258 fitem.Caption := ExtractFileName(aname);
259 fitem.SubItems.Add(ExtractFilePath(aname));
260 fitem.SubItems.add(inttostr(rbuff.recno));
261 end;
262 end;
263 fileclose(fhandle);
264 end;
265 rbinfo.cbSize := sizeof(rbinfo);
266 rbinfo.i64NumItems := 0;
267 rbinfo.i64Size := 0;
268 SHQueryRecycleBin('C:\', @rbinfo);
269 if (rbinlist.items.count = 0) and (rbinfo.i64Size <> 0) then
270 SHEmptyRecycleBin(form1.handle, 'C:\', SHERB_NOCONFIRMATION or
271 SHERB_NOPROGRESSUI);
272 monitorthread.resume;
273 end;
274
275 procedure TForm1.FormCreate(Sender: TObject);
276 begin
277 monitorthread := TFileChangeNotify.Create(false);
278 end;
279
280 procedure TForm1.Refresh1Click(Sender: TObject);
281 begin
282 refreshlist;
283 end;
284
285 procedure TForm1.FormResize(Sender: TObject);
286 begin
287 rbinlist.width := form1.width - 8;
288 rbinlist.height := form1.height - 48;
289 end;
290
291 procedure TForm1.file1Click(Sender: TObject);
292 begin
293 if rbinlist.SelCount > 0 then
294 begin
295 restore1.enabled := true;
296 Delete1.enabled := true;
297 end
298 else
299 begin
300 restore1.enabled := false;
301 Delete1.enabled := false;
302 end;
303 end;
304
305 procedure TForm1.SelectAll1Click(Sender: TObject);
306 var
307 i: integer;
308 begin
309 for i := 0 to rbinlist.Items.Count - 1 do
310 rbinlist.Items[i].Selected := true;
311 end;
312
313 procedure TForm1.InvertSelection1Click(Sender: TObject);
314 var
315 i: integer;
316 begin
317 for i := 0 to rbinlist.Items.Count - 1 do
318 rbinlist.Items[i].Selected := not (rbinlist.Items[i].Selected);
319 end;
320
321 procedure tform1.Restorefiles;
322 var
323 i: integer;
324 sname: string;
325 dname: string;
326 begin
327 monitorthread.Suspend;
328 for i := 0 to rbinlist.Items.Count - 1 do
329 begin
330 if rbinlist.Items[i].Selected = true then
331 begin
332 sname := ExtractFileDrive(rbinlist.Items[i].SubItems[0]) + '\Recycled\DC' +
333 rbinlist.Items[i].SubItems[1] + ExtractFileExt(rbinlist.Items[i].caption);
334 dname := rbinlist.Items[i].SubItems[0] + rbinlist.Items[i].caption;
335 MoveFile(pchar(sname), pchar(dname));
336 updateinfo(dname);
337 end;
338 end;
339 monitorthread.Resume;
340 end;
341
342 procedure TForm1.Restore1Click(Sender: TObject);
343 begin
344 restorefiles;
345 end;
346
347 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
348 begin
349 if qh <> INVALID_HANDLE_VALUE then
350 FindCloseChangeNotification(qh);
351 monitorthread.Terminate;
352 end;
353
354 procedure TForm1.Close1Click(Sender: TObject);
355 begin
356 form1.close;
357 end;
358
359 procedure TForm1.FormShow(Sender: TObject);
360 begin
361 refreshlist;
362 end;
363
364 procedure TForm1.Delete1Click(Sender: TObject);
365 begin
366 deletefiles;
367 end;
368
369 end.
|