RemoveDirectory()
被記錄爲僅標記用於刪除的目錄。我有一個應用程序,我必須確定該目錄實際上已被刪除(因爲我創建了一個具有相同名稱的新目錄,或者遞歸刪除目錄)。如何在Windows同步中刪除目錄
我的第一個想法是使用GetFileAttributes()
來測試該目錄是否仍然存在,或使用SHFileOperation()
進行刪除。但是當進行長時間測試時,在某些時候兩種解決方案都失敗 - CreateDirectory()
失敗。
有沒有解決方案呢?
RemoveDirectory()
被記錄爲僅標記用於刪除的目錄。我有一個應用程序,我必須確定該目錄實際上已被刪除(因爲我創建了一個具有相同名稱的新目錄,或者遞歸刪除目錄)。如何在Windows同步中刪除目錄
我的第一個想法是使用GetFileAttributes()
來測試該目錄是否仍然存在,或使用SHFileOperation()
進行刪除。但是當進行長時間測試時,在某些時候兩種解決方案都失敗 - CreateDirectory()
失敗。
有沒有解決方案呢?
道格拉斯尼爾在2015年CppCon的video涵蓋解決方案的詳細信息,從7:30開始。
這個想法是首先將文件或目錄重命名(移動)到另一個地方(在同一個捲上),這是同步發生的,然後刪除它,這是異步發生的。
考慮這個樹:
C:\Users\me\
foo\
bar\
obsolete.txt
如果您嘗試刪除obsolete.txt
後刪除bar
,它可能會失敗,因爲可以有一個延遲之前obsolete.txt
是真的刪除。
而是想你首先移動obsolete.txt
到C:\Users\me
,並給它一個臨時名稱,以確保它不與其他obsolete.txt
目錄中的碰撞。也許你用一個GUID作爲前綴,如2DCD7863-456C-4B6C-AD84-C4F5E8009D81_obsolete.txt
。現在,您可以使用該臨時名稱刪除該文件,並且,即使在真正刪除之前存在延遲,您也知道bar
確實是空的。您現在可以刪除bar
或在bar
中創建新的obsolete.txt
,而不用擔心發生衝突。
要刪除bar
(目錄),以便刪除foo
(您要刪除的樹的根目錄),您可以玩同一個遊戲。將它移動到根目錄的父級,請撥打RemoveDirectory
,然後按照您的快樂方式進行操作,以知道它最終會被刪除。
我相信這不適用於目錄。我有權寫入父目錄並不總是這樣。所以我不能移動它。其次,我也無法將它移動到%TEMP%,因爲%TEMP%可以位於不同的驅動器上,而且「MoveFile」無法在驅動器之間移動目錄。 – RobertK
@RobertK,如果你有權刪除'foo',那麼你是否有權寫'foo's parent?如果不是層次結構中的所有內容都針對同一個所有者負責,我想你可能會遇到配額問題,但這似乎不太可能。 (的確,'%TEMP'可以在不同的驅動器上,這是一個問題。) –
可能的選項:
刪除目錄,並檢查其存在後
如果沒有手柄是開着的,將被刪除。如果手柄仍然打開,還有另一個問題。或者,您可以在每次存在檢查後等待幾秒,直到它消失。
刪除目錄中的所有文件
您提到您要重新創建它,請刪除其內容。這樣做可以讓您查看目錄中的哪些文件/文件夾仍然打開。
如果目錄不是空的,RemoveDirectory()會失敗。 –
如上所述,即使存在檢查成功(=目錄不再存在),創建具有相同名稱的目錄也可能失敗。 – RobertK
也許您可以先將目錄重命名爲(隨機名稱),然後將其標記爲刪除。它最終會被刪除。然後,您可以始終使用原始名稱創建目錄。 – rveerd
當您嘗試對目錄執行任何操作時,您會收到「訪問被拒絕」錯誤。你就是這麼知道的。解決方案,好吧,不。這與嘗試覆蓋文件並且該文件已被其他進程使用並沒有根本的區別。您必須通過查找該過程或等待完成才能解決問題。這是自己造成的原因往往很難診斷。像反惡意軟件或將您的程序的當前工作目錄設置爲同一目錄。 –
誰說「只標記要刪除的目錄」?在MSDN中寫入「RemoveDirectory函數將關閉時刪除的目錄標記爲因此,直到該目錄的最後一個句柄關閉,該目錄才被刪除。」這意味着該目錄在使用時不會被刪除。但是,如果「最後一個句柄」關閉,它將被刪除 - 也許立即? http://stackoverflow.com/questions/2809788/impossible-to-remove-directory?rq=1 – i486