2009-06-08 5 views
3

私のWin32アプリケーションは、機能している間に指定された一時フォルダ内で多数のディスク操作を実行し、真剣に再設計することは問題になりません。作業ディレクトリをスキャンするウイルス対策を合理的に回避できますか?

一部のクライアントには、同じ一時ディレクトリをスキャンするウイルス対策ソフトウェアがあります(すべてをスキャンするだけです)。私たちは彼らにそれを無効にするように話してみました - それはうまくいかないので、どちらも問題ありません。

私のアプリケーションは、非常に時間がかかり、オペレーティングシステムによってロックされているファイルに操作を実行しようとします。共有違反が発生し、アプリケーションでエラーが発生します。これは、平均して3分に1回程度起こります。

ほとんどの一般的なシナリオでは、一時フォルダには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

+0

"cicurrent reads only"モードでそれを開くかもしれません。これはファイルの上書きを禁止します。確かに言えません - アンチウイルス開発者は私よりもよく分かっています。 – sharptooth

答えて

1

あなたがこれを行うために必要なコードでいくつかの場所を持っている場合は、私は、機能的なアプローチを取ることをお勧めしますファイルを開くことができません。

我々は戻っシマンテックと2002時間枠内で経験したファイルは、この順序で更新されたときMSDev6とした共通の問題:

ファイルが
  • 内容をメモリに変更されて開かれ
    1. アプリケーションは変更をコミットする必要があります
    2. アプリケーションは新しいファイルのコピー+変更で新しいtmpファイルを作成します
    3. アプリケーションは古いファイルを削除します
    4. 古いファイル名に
    5. アプリケーションをコピーしtmpファイルは
    6. アプリケーションは、ファイルの作成とを防止削除問題は、Symantecが減速に何かをするだろうステップ5とステップ6の間に起こるであろう

    tmpファイルを削除します同じ名前(CreateFileがERROR_DELETE_PENDINGを返しました)。 MSDev6はそれに気付かず、ステップ6が失敗したことを意味します。ステップ7はまだ起こった。最終的にオリジナルの削除が完了します。そのファイルはもはやディスクには存在しませんでした!

    AVGでは、変更されたばかりのファイルを開くことが断続的に問題になっています。

    私たちの解像度は、問題のように合理的なループでtry/catchでした。私たちのループ数は5です。

  • 1

    ファイルハンドルを解放しないようにアプリケーションを変更できますか?あなた自身がファイルをロックしていると、antivirアプリケーションはそれをスキャンすることができません。

    そうしないと、あなたのような戦略が役立ちます。なぜなら、それは確率を減らすだけだから問題を解決しないからです。

    1

    非常に問題です。私が持っているほとんどのアイデアは、あなたが望んでいない方向(例えば、再設計)に入ります。

    ディレクトリにあるファイルの数がわかりませんが、の場合はではない場合、プログラムの実行中にすべてのファイルを開いてロックすることで問題を回避できます。

    このようにして、ウィルススキャナはあなたのファイルへのアクセスを中断する機会はもうありません。

    1

    ウイルス対策ソフトウェア、バックアップユーティリティ、またはユーザー自身でさえ、他のプロセスがファイルを開く可能性がある場合は、その可能性をコードする必要があります。

    あなたのソリューションは、おそらく最もエレガントではありませんが、ReasonableNumberが十分に大きい限り、確かに機能しますが、これまでは妥当な数値として10を使用していました。私は確かにそれ以上に行くことはありませんし、5などの低い値で逃げることができます。

    睡眠の価値? 100msまたは200ms以下であること

    ほとんどの場合、アプリケーションは最初にファイルを取得することを覚えておいてください。

    4

    スキャン中にファイルをロックするウイルススキャナは非常に悪いです。ウィルススキャナを持っている人には、この悪いことは脳を置き換える必要があります;-)

    大丈夫です。ファイルが他のプロセスによってロックされている場合は、提案したように「再試行」戦略を使用することができます。OTOH、これらのファイルを閉じてからもう一度開く必要がありますか?あなたのプロセスが完了するまでそれらを開いたままにすることはできませんか? ヒント:ファイルをもう一度開こうとすると、遅延(スリープ)が追加されます。約100ミリ秒で十分です。ウイルススキャナがファイルを開いたままにしておくと、それは本当に悪いスキャナです。彼らが見ている例外メッセージは、悪いスキャナには当てはまりません。 通常、3回まで試してみてください。 - >開いたら、失敗したらもう一度試してください。もう一度試してみてください。

    ユーザーフレンドリーな方法でクラッシュすることを忘れないでください。

    +0

    その多くのファイルでは、VSを個々のファイルにロックするのではなく、ディレクトリをロックしているOSであるのだろうかと思います。 VS *は共有削除のためにオープンしていなければなりません。これは可能な限り最もオープンなオープンです。 –

    2

    ファイルの大きさにもよりますが、10秒から100秒のKbでは、100ms(0.1秒)で5回の試行で十分です。しばらくの間にエラーが発生した場合は、待ち時間を倍にしますが、YMMV。私は結果シマンテックとAVGの両方によって作られたウイルス対策ソフトウェアとの経験を持っていた

    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; 
         } 
        } 
    } 
    
    +1

    100ms!= 0.01sec –

    +0

    0.1を意味しない0.1を意味する。 –

    関連する問題