2013-11-09 22 views
6
私は、私が以前にユーザーの%TEMP%フォルダに作成されていたことを読んで、次のコードを使用すると、ファイルを開いてい

:一部のユーザーのコンピュータでFileShare.Deleteを使用するとUnauthorizedAccessExceptionが発生する可能性がありますか?

new FileStream(cacheFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete); 

が、これは時々メッセージ」とUnauthorizedAccessExceptionをスローしますパスへのアクセスは拒否されました "。私はこれを再現できませんでした。私の初期の推測では、ウイルス対策エンジンやインデックスエンジンがファンキーなことをしているということですが、このコードが "FileShare.Delete"を使用していることに気付きました。

"FileShare.Delete"を使用するとUnauthorizedAccessExceptionが発生するシナリオはありますか?

答えて

12

はい、FileShare.Deleteはこの問題を引き起こす傾向があります。バックグラウンドで実行され、ファイル、ファイルインデクサ、およびウイルススキャナをスキャンするプログラムで使用される一般的な例です。

FileShare.Deleteは、の別のプロセスでは、バックグラウンドプロセスにまだファイルが開いていて読み取り中であってもファイルを削除できます。他のプロセスは、ファイルが実際に消えていないことを知っているので、ファイルが実際に消えていないことに気づかないでしょう。

問題は、他のプロセスが実際に削除されているファイルに依存していて何か他のことをしているときに始まります。通常、同じ名前の新しいファイルを作成することによってトリガされます。特に、保存が失敗した場合にバックアップなしで完全なデータ損失が発生するので、ファイルを保存するのは非常に賢明な方法ですが、この間違いは非常に一般的です。

ファイルのディレクトリエントリがまだ存在するため、ファイルが開いている最後のプロセスがハンドルを閉じるまで、このファイルは消えません。ファイルをもう一度開こうとする他のプロセスは、エラー5、「アクセス拒否」でスラップされます。ファイルを削除して再作成しようとするプロセスを含む。

回避策は、ファイルを上書きしようとする前にファイルの名前を変更して、常に「トランザクション」保存を使用することです。 ReplaceFile()を持つネイティブwinapiで、File.Replace()で.NETで使用できます。また、簡単に手で行われ、ワークフローは次のとおりです。失敗した場合

  1. が失敗した
  2. は、元のファイル名を使用して新しいファイルを作成する場合は停止し、バックアップファイル名に、古いファイルの名前を変更、停止、バックアップファイルを削除します
  3. 失敗したバックアップファイルを削除した場合、バックバックアップの名前を変更、無視失敗

ステップ2は、任意のデータの損失は存在しないことを確実に何かがうまくいかない場合は、元のファイルはそのまま残ります。ステップ4は、FileShareを保証します。削除は意図どおりに機能し、他のプロセスがハンドルを閉じると、バックアップファイルは最終的に消えます。

3

私はこれを再現するシナリオを見つけました:このプログラムを実行し、ファイル:

static void Main(string[] args) 
    { 
     string cacheFileName = @"C:\temp.txt"; 
     using (var filestream = new FileStream(cacheFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, 4096, FileOptions.SequentialScan)) 
     { 
      filestream.Read(new byte[100], 1, 1); 
      Console.ReadLine(); 
      GC.KeepAlive(filestream); 
     } 
     Console.WriteLine("Done!"); 
    } 
} 

は "\ TEMP.TXT C" を作成します。 Explorer/TotalCommanderでファイルを削除しようとすると、ファイルは削除されません。その後、プログラムを再度実行すると、UnauthorizedAccessExceptionがスローされます。両方の.exesを閉じると、ファイルが最後に削除されたように見えます。

"FileShare.Delete"を削除すると、この問題が解決されます。使用中にファイルを削除しようとしないためです。

関連する問題