Search code examples
delphidelphi-6

Can't delete folder from a different partition


I'm having a problem when deleting folders that are on a different partition (E:/) from my software. I can delete files, using the DeleteFile function, but I'm not able to delete a folder using the code below:

function RemoveDirectory(strDir : String) : Boolean;
var
  SearchRec : TSearchRec;
  strFile   : String;
  nResult   : Integer;
begin
  try
    Result := false;

    nResult := FindFirst(strDir + '*', faAnyFile, SearchRec);

    while (nResult = 0) do
      begin
        if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
          begin
            strFile := strDir +  SearchRec.Name;

            if FileExists(strFile) then
              DeleteFile(strFile)
            else if DirectoryExists(strFile) then
              RemoveDirectory(strFile);
          end;
        nResult := FindNext(SearchRec);
      end;

    Result := RemoveDir(strDir);
  finally
    FindClose(SearchRec);
  end;
end;

With this code I can delete folders that are on the same partition from my software. Somebody knows what's going on? Is it because it's on a different partition?


Solution

  • You are trying to remove directories while you still have open search handles. Since this is a recursive function, if the directory hierarchy is deep, you would have multiple search handles open at a time and that is a lot of system resources being used when the deeper folders are reached.

    It is better to collect the immediate subfolders into a temp list, then you can close the current search handle before iterating that list. This way, there is ever only 1 search handle active at a time, and there is no search handle active when each folder is actually being deleted.

    Try this:

    function RemoveDirectory(strDir : String) : Boolean;
    var
      SearchRec : TSearchRec;
      nResult,i : Integer;
      SubFolders: TStringList;
    begin
      SubFolders := nil;
      try
        strDir := IncludeTrailingPathDelimiter(strDir);
    
        nResult := FindFirst(strDir + '*', faAnyFile, SearchRec);
        if (nResult = 0) then
        try
          repeat
            if (SearchRec.Attr and faDirectory) = 0 then
              DeleteFile(strDir + SearchRec.Name)
            else
            begin
              if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
              begin
                if not Assigned(SubFolders) then SubFolders := TStringList.Create;
                SubFolders.Add(strDir + SearchRec.Name);
              end;
            end;
          until FindNext(SearchRec) <> 0;
        finally
          FindClose(SearchRec);
        end;
    
        if Assigned(SubFolders) then
        begin
          for i := 0 to SubFolders.Count-1 do
            RemoveDirectory(SubFolders[i]);
        end;
      finally
        SubFolders.Free;
      end;
    
      Result := RemoveDir(strDir);
    end;
    

    If this still fails, then someone else outside of your app/loop is actually using the directories, and you can use a tool like SysInternals Process Explorer to check that.