2013-05-02 232 views
4

如何刪除包含一些文件和一些非空子目錄的目錄。我試過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; 

但它不會在編譯提誤差未聲明的標識符ClearFolder面具遞歸。我的要求是「如果WALLPAPER文件夾下存在任何子文件夾,它將被刪除」。同一個子文件夾可能包含任意數量的非空子文件夾或文件。

回答

7

那麼,對於初學者,SHFileOperation在Windows 7或Windows 8上沒有兼容性問題。是的,現在推薦您使用IFileOperation來代替。但是如果你想支持XP這樣的老式操作系統,那麼你可以並且應該只需要撥打SHFileOperation。它工作並將繼續工作。在Windows 7和Windows 8上使用它非常好,如果它從Windows刪除,我會戴上帽子。微軟竭盡全力保持向後兼容性。所以,在我看來,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; 

這刪除目錄及其內容。您需要遍歷頂層目錄,然後爲您找到的每個子目錄調用此函數。

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或更高版本的情況下直接刪除而不發送到「回收站」。

+0

@ user235 ....操作系統不會讓一個正常的應用程序從c:\ windows刪除文件! – Ampere 2014-04-08 11:31:43

0

這是一個非常完整的功能,可以同時處理文件和文件夾。 它允許您指定以下參數:

  • DeleteToRecycle
  • ShowConfirm
  • TotalSilence

{------------------ ---------------------------------------------
DELETE FILE
刪除文件/文件夾到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; 
相關問題