2010-09-07 74 views
3

我正在打開一個具有讀取訪問權限的文件,並允許後續讀取|寫入|刪除文件共享訪問文件(加尾文件)。如果文件在處理過程中被刪除,有一種方法可以檢測到該文件正在等待刪除(請參閱文件部分http://msdn.microsoft.com/en-us/library/aa363858(v=VS.85).aspx)?如果某個外部進程(擁有進程)發出了刪除,我想盡快關閉我的句柄以允許刪除文件,以免干擾擁有進程中的任何邏輯。在打開文件中檢測文件刪除

我在C#中查看沒有檢測掛起刪除的方法。該文件是使用FileStream對象打開的。有沒有一些方法來檢測C#或其他窗口函數中的刪除?

+0

應該提及您正在使用DELETE_ON_CLOSE/FILE_SHARE_DELETE。我懷疑這是非常常見的用法。 – 2010-09-07 22:56:56

回答

0

我會使用不同的信號機制。(我假定所有的文件訪問都在你的控制之內,而不是來自於一個封閉的外部程序,主要是由於使用了標誌。)

我能想到的那些範圍內的唯一「解決方案」是一個民意調查在文件訪問和檢查你回來的異常(如果有的話)。也許有一些更棘手的問題(在比win32文件API更低的層次上),但是這已經在「uhg路徑」中了:-)

+1

我接受這個答案,因爲這是我所能做到的。有一個打開的文件句柄,每次我需要返回並從句柄中讀取時,我也嘗試再次打開該文件。如果我回到UnauthorizedAccessException(請參閱msdn),那麼我假設文件已被刪除並關閉我的句柄。我相信這是昂貴的,但沒有什麼我可以想出。 – 2010-09-08 14:26:51

0

FileSystemWatcher可能是最接近的事情,但它無法檢測到「掛起」刪除;當文件被刪除時,FileSystemWatcher會引發一個事件,並且您可以附加一個處理程序,它將優雅地中斷文件處理。如果在打開文件時獲得的鎖定(或缺少一個)可以完全刪除該文件,那麼只要關閉只讀FileStream就不會影響文件系統。

文件觀察器的基本步驟是創建一個,將FileInfo對象的實例傳遞給構造函數。通過實例化FileInfos可以低成本創建,將文件的路徑和文件名作爲字符串傳遞給它。然後,將其NotifyFilter設置爲您要在此文件上觀看的文件系統修改的類型。最後,將進程的事件處理程序附加到OnDeleted事件。這個事件處理程序可能很簡單,只要在您的主進程可以讀取的位置設置一個位標誌,然後關閉FileStream即可。然後,您會在下次嘗試使用流時遇到異常情況;抓住它,閱讀國旗,如果它的設置恰好停止做文件的東西。你也可以把文件處理放在一個單獨的工作線程中,事件處理程序可以通過一些優美的方法告訴線程死掉。

+0

問題是我有一個打開的文件句柄,這將阻止刪除完成 - 它正在等待。我需要檢測刪除,所以我可以關閉我的句柄,以便刪除完成。 – 2010-09-07 16:43:13

+1

這是不可能的afaik。刪除將失敗 - 您真正要求的是在另一個進程中檢測刪除慾望的方式。在操作系統中實現一種方法來通知所有當前文件用戶,其他進程正在嘗試刪除正在使用的文件,直到其他用戶決定關閉其使用(如果他們拒絕?),等待刪除,這是不實際的。如果刪除過程因爲某種原因而改變主意或退出,該怎麼辦?相互作用太糟糕了,無法思考。 – 2010-09-07 17:06:07

+0

你是說擁有進程的請求刪除文件將失敗?如果是這樣,那是不正確的。刪除成功,文件掛起刪除,直到所有句柄關閉。一旦沒有更多的句柄打開文件,它將被刪除。在掛起刪除期間,後續訪問文件的請求會收到拒絕訪問異常。請參閱:http://msdn.microsoft.com/en-us/library/aa363915(v=VS.85).aspx或http://msdn.microsoft.com/en-us/library/aa363858(v=VS 0.85)的.aspx。 – 2010-09-07 17:26:05

0

如果文件足夠小,應用程序可以處理文件的拷貝,而不是文件本身。另外,如果您的應用程序需要知道擁有的進程是否刪除了原始文件,請在該文件上設置一個FileSystemWatcher(FSW)。當文件消失時,FSW可以設置一個標誌來中斷處理:

private bool _fileExists = true; 

public void Process(string pathToOriginalFile, string pathToCopy) 
{ 
    File.Copy(pathToOriginalFile, pathToCopy); 

    FileSystemWatcher watcher = new FileSystemWatcher(); 
    watcher.Path = pathToOriginalFile; 
    watcher.Deleted += new FileSystemEventHandler(OnFileDeleted); 

    bool doneProcessing = false; 
    watcher.EnableRaisingEvents = true; 

    while(_fileExists && !doneProcessing) 
    { 
     // process the copy here 
    } 

    ... 
} 

private void OnFileDeleted(object source, FileSystemEventArgs e) 
{ 
    _fileExists = false; 
} 
+0

同樣,FileSystemWatcher將不起作用,因爲在文件的所有句柄都關閉之前文件不會被刪除。由於我有一個文件句柄,它正在等待刪除,直到我關閉我的句柄。 – 2010-09-08 14:23:53

+0

您將複製文件後,將釋放原始文件的句柄。如果我沒有弄錯,FSW將處理文件所在的_directory_,而不是該文件的句柄。 – 2010-09-08 18:30:33

+0

你說得對,我應該仔細閱讀你的答案。這些文件可能可能是任何大小,但在任何情況下處理副本都是不可行的。 – 2010-09-09 14:14:32

0

不,沒有乾淨的方法來做到這一點。如果你擔心打開和/或修改文件的其他進程,那麼oplocks可以幫助你。但是,如果您只是在查找刪除處置何時被設置爲刪除的通知,則沒有一種簡單的方法來執行此操作(無法構建文件系統篩選器,掛接API等等,所有這些對於應用程序來說都很嚇人做沒有很好的理由)。