2016-09-13 81 views
0

RemoveDirectory()被記錄爲僅標記用於刪除的目錄。我有一個應用程序,我必須確定該目錄實際上已被刪除(因爲我創建了一個具有相同名稱的新目錄,或者遞歸刪除目錄)。如何在Windows同步中刪除目錄

我的第一個想法是使用GetFileAttributes()來測試該目錄是否仍然存在,或使用SHFileOperation()進行刪除。但是當進行長時間測試時,在某些時候兩種解決方案都失敗 - CreateDirectory()失敗。

有沒有解決方案呢?

+1

也許您可以先將目錄重命名爲(隨機名稱),然後將其標記爲刪除。它最終會被刪除。然後,您可以始終使用原始名稱創建目錄。 – rveerd

+0

當您嘗試對目錄執行任何操作時,您會收到「訪問被拒絕」錯誤。你就是這麼知道的。解決方案,好吧,不。這與嘗試覆蓋文件並且該文件已被其他進程使用並沒有根本的區別。您必須通過查找該過程或等待完成才能解決問題。這是自己造成的原因往往很難診斷。像反惡意軟件或將您的程序的當前工作目錄設置爲同一目錄。 –

+1

誰說「只標記要刪除的目錄」?在MSDN中寫入「RemoveDirectory函數將關閉時刪除的目錄標記爲因此,直到該目錄的最後一個句柄關閉,該目錄才被刪除。」這意味着該目錄在使用時不會被刪除。但是,如果「最後一個句柄」關閉,它將被刪除 - 也許立即? http://stackoverflow.com/questions/2809788/impossible-to-remove-directory?rq=1 – i486

回答

1

道格拉斯尼爾在2015年CppCon的video涵蓋解決方案的詳細信息,從7:30開始。

這個想法是首先將文件或目錄重命名(移動)到另一個地方(在同一個捲上),這是同步發生的,然後刪除它,這是異步發生的。

考慮這個樹:

C:\Users\me\ 
    foo\ 
    bar\ 
     obsolete.txt 

如果您嘗試刪除obsolete.txt後刪除bar,它可能會失敗,因爲可以有一個延遲之前obsolete.txt真的刪除。

而是想你首先移動obsolete.txtC:\Users\me,並給它一個臨時名稱,以確保它不與其他obsolete.txt目錄中的碰撞。也許你用一個GUID作爲前綴,如2DCD7863-456C-4B6C-AD84-C4F5E8009D81_obsolete.txt。現在,您可以使用該臨時名稱刪除該文件,並且,即使在真正刪除之前存在延遲,您也知道bar確實是空的。您現在可以刪除bar或在bar中創建新的obsolete.txt,而不用擔心發生衝突。

要刪除bar(目錄),以便刪除foo(您要刪除的樹的根目錄),您可以玩同一個遊戲。將它移動到根目錄的父級,請撥打RemoveDirectory,然後按照您的快樂方式進行操作,以知道它最終會被刪除。

+0

我相信這不適用於目錄。我有權寫入父目錄並不總是這樣。所以我不能移動它。其次,我也無法將它移動到%TEMP%,因爲%TEMP%可以位於不同的驅動器上,而且「MoveFile」無法在驅動器之間移動目錄。 – RobertK

+0

@RobertK,如果你有權刪除'foo',那麼你是否有權寫'foo's parent?如果不是層次結構中的所有內容都針對同一個所有者負責,我想你可能會遇到配額問題,但這似乎不太可能。 (的確,'%TEMP'可以在不同的驅動器上,這是一個問題。) –

0

可能的選項:

  • 刪除目錄,並檢查其存在後
    如果沒有手柄是開着的,將被刪除。如果手柄仍然打開,還有另一個問題。或者,您可以在每次存在檢查後等待幾秒,直到它消失。

  • 刪除目錄中的所有文件
    您提到您要重新創建它,請刪除其內容。這樣做可以讓您查看目錄中的哪些文件/文件夾仍然打開。

+1

如果目錄不是空的,RemoveDirectory()會失敗。 –

+0

如上所述,即使存在檢查成功(=目錄不再存在),創建具有相同名稱的目錄也可能失敗。 – RobertK