【问题标题】:Delete Directory with non empty subdirectory and files删除具有非空子目录和文件的目录
【发布时间】:2013-05-02 11:20:48
【问题描述】:

如何删除一个包含一些文件和一些非空子目录的目录。
我试过SHFileOperation Function。它在Windows 7 中存在一些兼容性问题。
然后我尝试了IFileOperation Interface。但它在 Windows XP 中不兼容。 然后我按照David Heffernan 的建议尝试了以下代码:

procedure TMainForm.BitBtn01Click(Sender: TObject);
var
  FileAndDirectoryExist: TSearchRec;
  ResourceSavingPath : string;
begin
  ResourceSavingPath := (GetWinDir) + 'Web\Wallpaper\';
  if FindFirst(ResourceSavingPath + '\*', faAnyFile, FileAndDirectoryExist) = 0 then
  try
    repeat
      if (FileAndDirectoryExist.Name <> '.') and (FileAndDirectoryExist.Name <> '..') then
        if (FileAndDirectoryExist.Attr and faDirectory) <> 0 then
          //it's a directory, empty it
          ClearFolder(ResourceSavingPath +'\' + FileAndDirectoryExist.Name, mask, recursive)
        else
          //it's a file, delete it
          DeleteFile(ResourceSavingPath + '\' + FileAndDirectoryExist.Name);
    until FindNext(FileAndDirectoryExist) <> 0;
    //now that this directory is empty, we can delete it
    RemoveDir(ResourceSavingPath);
  finally
    FindClose(FileAndDirectoryExist);
  end;
end;

但它不会在 ClearFolderma​​skrecursive 处编译提及错误作为未声明的标识符。我的要求是“如果 WALLPAPER 文件夹下存在任何子文件夹,它将被删除”。同一个子文件夹可以包含任意数量的非空子文件夹或文件。

【问题讨论】:

标签: delphi


【解决方案1】:

好吧,对于初学者来说,SHFileOperation 在 Windows 7 或 Windows 8 上没有兼容性问题。是的,现在建议您改用IFileOperation。但是,如果您想支持 XP 等较旧的操作系统,那么您可以而且应该致电SHFileOperation。它工作并将继续工作。在 Windows 7 和 Windows 8 上使用它非常好,如果它从 Windows 中删除,我会吃掉我的帽子。 Microsoft 竭尽全力保持向后兼容性。所以,SHFileOperation 在我看来是你最好的选择。

您基于FindFirst 的方法失败了,因为您需要将它放在一个单独的函数中以允许递归。我在其他答案中发布的代码不完整。这是一个完整的版本:

procedure DeleteDirectory(const Name: string);
var
  F: TSearchRec;
begin
  if FindFirst(Name + '\*', faAnyFile, F) = 0 then begin
    try
      repeat
        if (F.Attr and faDirectory <> 0) then begin
          if (F.Name <> '.') and (F.Name <> '..') then begin
            DeleteDirectory(Name + '\' + F.Name);
          end;
        end else begin
          DeleteFile(Name + '\' + F.Name);
        end;
      until FindNext(F) <> 0;
    finally
      FindClose(F);
    end;
    RemoveDir(Name);
  end;
end;

这将删除一个目录及其内容。您可能希望遍历顶级目录,然后为找到的每个子目录调用此函数。

【讨论】:

  • FindFirst 是否也可以在 Lazarus 的 FTP 服务器上工作,因为我需要删除那里的目录
【解决方案2】:

最后我实现了以下代码:

uses
  ShellAPI;
...
...
function GetWinDir: string;
var
  WindowsDirectory: array[0..MAX_PATH] of Char;
begin
   GetWindowsDirectory(WindowsDirectory, MAX_PATH - 1);
   SetLength(Result, StrLen(WindowsDirectory));
   Result := IncludeTrailingPathDelimiter(WindowsDirectory);
end;
...
...
procedure DeleteDirectory(const DirName: string);
var
  FileFolderOperation: TSHFileOpStruct;
begin
  FillChar(FileFolderOperation, SizeOf(FileFolderOperation), 0);
  FileFolderOperation.wFunc := FO_DELETE;
  FileFolderOperation.pFrom := PChar(ExcludeTrailingPathDelimiter(DirName) + #0);
  FileFolderOperation.fFlags := FOF_SILENT or FOF_NOERRORUI or FOF_NOCONFIRMATION;
  SHFileOperation(FileFolderOperation);
end;
...
...
procedure TMainForm.BitBtn01Click(Sender: TObject);
begin
  DeleteDirectory((GetWinDir) + '\Web\Wallpapers\');
end
...
...

请不要提及任何有关“TrailingPathDelimiter”的内容,我是有意实施的。我成功地遇到了一个问题,即在 Windows XP 的情况下文件或文件夹成功删除而无需进入“回收站”,但在 Vista 及更高版本的情况下,这些文件进入“回收站”,我没有任何选项在 Vista 或更高版本的情况下,直接删除而不发送到“回收站”。

【讨论】:

    【解决方案3】:

    这是一个非常完整的功能,适用于文件和文件夹。 它允许您指定以下参数:

    • DeleteToRecycle
    • 显示确认
    • 完全沉默

    {---------------------------------------------- -----------------
    删除文件
    将文件/文件夹删除到 RecycleBin。
    -------------------------------------------------- --------------}

    function RecycleItem(CONST ItemName: string; CONST DeleteToRecycle: Boolean= TRUE; CONST ShowConfirm: Boolean= TRUE; CONST TotalSilence: Boolean= FALSE): Boolean;
    VAR
       SHFileOpStruct: TSHFileOpStruct;
    begin
     FillChar(SHFileOpStruct, SizeOf(SHFileOpStruct), #0);
     SHFileOpStruct.wnd              := Application.MainForm.Handle;                                   { Others are using 0. But Application.MainForm.Handle is better because otherwise, the 'Are you sure you want to delete' will be hidden under program's window }
     SHFileOpStruct.wFunc            := FO_DELETE;
     SHFileOpStruct.pFrom            := PChar(ItemName+ #0);                                          
     SHFileOpStruct.pTo              := NIL;
     SHFileOpStruct.hNameMappings    := NIL;
    
     if DeleteToRecycle
     then SHFileOpStruct.fFlags:= SHFileOpStruct.fFlags OR FOF_ALLOWUNDO;
    
     if TotalSilence
     then SHFileOpStruct.fFlags:= SHFileOpStruct.fFlags OR FOF_NO_UI
     else
       if NOT ShowConfirm
       then SHFileOpStruct.fFlags:= SHFileOpStruct.fFlags OR FOF_NOCONFIRMATION;
    
     Result:= SHFileOperation(SHFileOpStruct)= 0;
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      • 2017-10-08
      • 2013-01-07
      • 1970-01-01
      • 2012-05-31
      • 2016-10-16
      • 2012-04-02
      相关资源
      最近更新 更多