2009-06-08 28 views
3

我的Win32應用程序在運行時在指定的臨時文件夾中執行大量磁盤操作,並且嚴重重新設計它是不可能的。是否可以合理解決防病毒掃描工作目錄的問題?

某些客戶端具有可掃描相同臨時目錄的防病毒軟件(它只是掃描所有內容)。我們試圖說服他們禁用它 - 它不起作用,所以它也沒有問題。

每隔一段時間(類似於每一千個文件操作就有一次),我的應用程序嘗試對當時正在由防病毒軟件打開的文件執行操作,因此被操作系統鎖定。發生共享衝突並導致我的應用程序出錯。這種情況平均每三分鐘發生一次。

在大多數典型場景中,臨時文件夾最多可以包含100k個文件,所以我不喜歡讓它們隨時打開的想法,因爲這可能會在某些邊緣條件下導致資源用盡。

當我需要的文件被鎖定時,我的應用程序是否有一些合理的策略來應對情況?也許這樣?

for(int i = 0; i < ReasonableNumber; i++) { 
    try { 
     performOperation(); // do useful stuff here 
     break; 
    } catch(...) { 
     if(i == ReasonableNumber - 1) { 
      throw; //not to hide errors if unlock never happens 
     } 
    } 
    Sleep(ReasonableInterval); 
} 

這是一個可行的策略嗎?如果是這樣,我的申請應該重試多少次和多久?如果有什麼更好的想法?

+1

您確定防病毒已鎖定文件嗎?我無法得到爲什麼防病毒會鎖定一個文件?當它加載一個文件時,它應該允許共享。 – Canopus 2009-06-08 13:38:37

+0

也許它打開它「只允許cicurrent讀取」模式,這禁止覆蓋文件。無法確定 - 防病毒開發人員可能比我更瞭解。 – sharptooth 2009-06-08 13:44:21

回答

1

我已經與賽門鐵克和AVG導致由防病毒軟件的經驗在文件不可用於打開。

我們經歷了早在賽門鐵克2002年的時間框架是與MSDev6當一個文件在這個序列更新一個共同的問題:

  1. 打開一個文件時
  2. 內容在內存中修改
  3. 申請需要提交修改
  4. 應用程序創建新tmp文件與文件+新副本的修改
  5. 應用程序刪除舊文件
  6. 應用程序拷貝tmp文件到舊文件名
  7. 應用刪除tmp文件

將步驟5和6。賽門鐵克會做一些放緩之間發生的問題刪除防止文件與創建同名(CreateFile返回ERROR_DELETE_PENDING)。 MSDev6將無法注意到 - 意味着第6步失敗。雖然第7步仍然發生。原件的刪除最終會結束。所以文件不再存在於磁盤上!

對於AVG,我們遇到了間歇性問題,能夠打開剛被修改過的文件。

我們的解決方案在問題中是一個合理循環的嘗試/捕獲。我們的循環次數是5.

1

你能改變你的應用程序,所以你不釋放文件句柄嗎?如果您自己鎖定文件,antivir應用程序將無法掃描它。

否則像你這樣的策略會有所幫助,因爲它只會降低概率,但並不能解決問題。

1

嚴重的問題。大部分想法已經進入你不想要的方向(例如重新設計)。

我不知道您的目錄中有多少個文件,但如果它不是那麼您可以通過在程序運行時保持所有文件打開並鎖定的方式解決您的問題。

這種方式病毒掃描程序將沒有機會中斷您的文件訪問了。

1

如果有其他進程(無論是防病毒軟件,備份實用程序還是用戶本身)都可以打開文件,那麼您必須對此進行編碼。

只要ReasonableNumber足夠大,您的解決方案雖然也許不是最優雅的,但一定會有效 - 在過去,我用10作爲合理數字。我當然不會走得更高,你可以得到一個較低的值,如5。

睡眠的價值?最多100ms或200ms

請記住,大多數情況下,您的應用程序無論如何都會首次獲取文件。

4

在掃描文件時鎖定文件的virusscanner非常糟糕。有virusscanners的客戶需要更換他們的大腦... ;-)

好的,足夠的咆哮。如果一個文件被其他進程鎖定,那麼你可以像你所建議的那樣使用「再試一次」策略。OTOH,你真的需要關閉然後重新打開這些文件嗎?你不能讓它們開放直到你的過程完成了嗎? 一個提示:當您嘗試重新打開文件時,添加延遲(睡眠)。大約100毫秒應該足夠了。如果virusscanner將文件保持打開狀態,那麼它就是一臺真正的壞的掃描儀。掃描儀不好的客戶應該看到他們會看到的異常信息。 通常,最多嘗試三次... - >打開,失敗時再試一次,再次失敗時再試一次,第三次失敗只是崩潰。

記得以用戶友好的方式崩潰。

+0

有了這麼多的文件,我想知道是否是鎖定目錄的操作系統,而不是VS鎖定單個文件。 VS *應該*開放共享刪除,這是最寬鬆的開放可能。 – 2009-06-08 14:17:38

2

取決於你的文件有多大,但是對於10s到100s的Kb,我發現用100ms(0.1秒)5次就足夠了。如果偶爾碰到錯誤,請加倍等待,但是YMMV

如果你有哪些需要做這個代碼的一些地方,可能我建議採取注重功能的做法:

using System; 

namespace Retry 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int i = 0; 
      Utils.Retry(() => 
      { 
       i = i + 1; 
       if (i < 3) 
        throw new ArgumentOutOfRangeException(); 
      }); 
      Console.WriteLine(i); 
      Console.Write("Press any key..."); 
      Console.ReadKey(); 
     } 
    } 

    class Utils 
    { 
     public delegate void Retryable(); 
     static int RETRIES = 5; 
     static int WAIT = 100; /*ms*/ 
     static public void Retry(Retryable retryable) 
     { 
      int retrys = RETRIES; 
      int wait = WAIT; 
      Exception err; 
      do 
      { 
       try 
       { 
        err = null; 
        retryable(); 
       } 
       catch (Exception e) 
       { 
        err = e; 
        if (retrys != 1) 
        { 
         System.Threading.Thread.Sleep(wait); 
         wait *= 2; 
        } 
       } 
      } while(--retrys > 0 && err != null); 
      if (err != null) 
       throw err; 
     } 
    } 
}