Stephen Jackson
2003-07-22 10:36:09 UTC
Having trouble deleting directories from a program that finds them
using the TSearchRec/FindFirst/FindNext method. The path is deletable
before the search and also after the program has closed (using an
hardcoded <DeleteFile> or the FileExplorer), but not after a search
whilst the program is still running. It looks like the directory is
locked somehow but the directory is not opened? The files are deleted
using <DeleteFile> (Dirs by <RemoveDir>). Note all directories fail
when being deleted. Curiously the program works fine on Win95/98. I
am working on XP with FAT32. Anybody else had this?
Here is the search routine, which finds files and stores in a
TStringList:
==========================================================================
procedure GetFileNamesInDir(var FileNames: TStringList;
const Dir, FileMask: string; const Attribute: Integer;
const Recursive: Boolean; const PathType: TmyPathType;
const ClearList: Boolean = True); overload; {2+}{11~}{16~}
{=smj=============================================================}
// Creates a list of FileNames from a Dir.
// Dir: Start point.
// FileMask: Accepts wildcards i.e. 'A*.*'.
// Attribute: faAnyFile, faDirectory etc. (see Delphi's FindFirst
function).
// Recursive: Does it look within Sub Dir's.
// PathType: Determines the amount FileName path is returned.
// ptNone: Just the FileName, no Path.
// ptPartial: Path + Filename, not including the Start Dir path.
// ptFull: Full qualified Path + Filename.
var
RootDirLen: Integer;
procedure FindFilesIn(const Dir: string);
{=smj===================================}
var
RelativeDir: string;
procedure SaveFileName(const FileName: string);
{=smj=========================================}
begin
case PathType of
ptNone: FileNames.Add(FileName);
ptPartial: FileNames.Add(PathConcat(RelativeDir, FileName));
ptFull: FileNames.Add(PathConcat(Dir, FileName));
end;
end;
var
Status: Integer;
SearchRec: TSearchRec;
function Valid(const Attribute: Integer): Boolean;
{=smj============================================}
begin
Result :=
(SearchRec.Name <> '.') and
(SearchRec.Name <> '..') and
((Attribute = faAnyFile) or
(SearchRec.Attr and Attribute > 0));
end;
begin
if PathType = ptPartial then
// Relative Path required, create. (More efficient this way).
RelativeDir := Copy(Dir, RootDirLen + 1, Length(Dir));
Status := FindFirst(PathConcat(Dir, [FileMask]), Attribute,
SearchRec);
try
repeat
while Status = 0 do begin
if Valid(Attribute) then {4+}
SaveFileName(SearchRec.Name);
Status := FindNext(SearchRec);
end;
if Recursive then begin
// Check Sub-Dirs. {11+}
Status := FindFirst(
PathConcat(Dir, ['*.*']), faDirectory, SearchRec);
while Status = 0 do begin
if Valid(faDirectory) then
FindFilesIn(PathConcat(Dir, [SearchRec.Name]));
Status := FindNext(SearchRec);
end;
end;
until Status <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
end;
begin
if ClearList then {16~}
FileNames.Clear;
// Relative path pre-calculation.
if PathType = ptPartial then
if AnsiLastChar(Dir)^ = '\' then
RootDirLen := Length(Dir)
else
RootDirLen := Length(Dir) + 1;
FindFilesIn(Dir);
end;
Delete rountine:
================
procedure TfrmMain.bitDeleteClick(Sender: TObject);
{=smj=============================================}
var
deleted: Boolean;
i: Integer;
Pfn: string;
begin
for i := lsvHitlist.Items.Count - 1 downto 0 do begin
Pfn := lsvHitList.Items[i].Caption;
if FileGetAttr(Pfn) = faDirectory then
deleted := RemoveDir(Pfn)
else
deleted := DeleteFile(Pfn);
if deleted then
lsvHitlist.Items[i].Delete
else
lsvHitlist.Items[i].StateIndex := 1;
end;
UpdateUI();
end;
using the TSearchRec/FindFirst/FindNext method. The path is deletable
before the search and also after the program has closed (using an
hardcoded <DeleteFile> or the FileExplorer), but not after a search
whilst the program is still running. It looks like the directory is
locked somehow but the directory is not opened? The files are deleted
using <DeleteFile> (Dirs by <RemoveDir>). Note all directories fail
when being deleted. Curiously the program works fine on Win95/98. I
am working on XP with FAT32. Anybody else had this?
Here is the search routine, which finds files and stores in a
TStringList:
==========================================================================
procedure GetFileNamesInDir(var FileNames: TStringList;
const Dir, FileMask: string; const Attribute: Integer;
const Recursive: Boolean; const PathType: TmyPathType;
const ClearList: Boolean = True); overload; {2+}{11~}{16~}
{=smj=============================================================}
// Creates a list of FileNames from a Dir.
// Dir: Start point.
// FileMask: Accepts wildcards i.e. 'A*.*'.
// Attribute: faAnyFile, faDirectory etc. (see Delphi's FindFirst
function).
// Recursive: Does it look within Sub Dir's.
// PathType: Determines the amount FileName path is returned.
// ptNone: Just the FileName, no Path.
// ptPartial: Path + Filename, not including the Start Dir path.
// ptFull: Full qualified Path + Filename.
var
RootDirLen: Integer;
procedure FindFilesIn(const Dir: string);
{=smj===================================}
var
RelativeDir: string;
procedure SaveFileName(const FileName: string);
{=smj=========================================}
begin
case PathType of
ptNone: FileNames.Add(FileName);
ptPartial: FileNames.Add(PathConcat(RelativeDir, FileName));
ptFull: FileNames.Add(PathConcat(Dir, FileName));
end;
end;
var
Status: Integer;
SearchRec: TSearchRec;
function Valid(const Attribute: Integer): Boolean;
{=smj============================================}
begin
Result :=
(SearchRec.Name <> '.') and
(SearchRec.Name <> '..') and
((Attribute = faAnyFile) or
(SearchRec.Attr and Attribute > 0));
end;
begin
if PathType = ptPartial then
// Relative Path required, create. (More efficient this way).
RelativeDir := Copy(Dir, RootDirLen + 1, Length(Dir));
Status := FindFirst(PathConcat(Dir, [FileMask]), Attribute,
SearchRec);
try
repeat
while Status = 0 do begin
if Valid(Attribute) then {4+}
SaveFileName(SearchRec.Name);
Status := FindNext(SearchRec);
end;
if Recursive then begin
// Check Sub-Dirs. {11+}
Status := FindFirst(
PathConcat(Dir, ['*.*']), faDirectory, SearchRec);
while Status = 0 do begin
if Valid(faDirectory) then
FindFilesIn(PathConcat(Dir, [SearchRec.Name]));
Status := FindNext(SearchRec);
end;
end;
until Status <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
end;
begin
if ClearList then {16~}
FileNames.Clear;
// Relative path pre-calculation.
if PathType = ptPartial then
if AnsiLastChar(Dir)^ = '\' then
RootDirLen := Length(Dir)
else
RootDirLen := Length(Dir) + 1;
FindFilesIn(Dir);
end;
Delete rountine:
================
procedure TfrmMain.bitDeleteClick(Sender: TObject);
{=smj=============================================}
var
deleted: Boolean;
i: Integer;
Pfn: string;
begin
for i := lsvHitlist.Items.Count - 1 downto 0 do begin
Pfn := lsvHitList.Items[i].Caption;
if FileGetAttr(Pfn) = faDirectory then
deleted := RemoveDir(Pfn)
else
deleted := DeleteFile(Pfn);
if deleted then
lsvHitlist.Items[i].Delete
else
lsvHitlist.Items[i].StateIndex := 1;
end;
UpdateUI();
end;