5

このコードサンプルを見てみましょう:

using System;
using System.IO;

namespace ConsoleApplication25
{
    class Program
    {
        static void Main()
        {
            var bytes = new byte[] { 1, 2, 3 };
            var trimChars = new[] { '"' };
            var path = Environment.CommandLine.Trim().Trim(trimChars);
            File.WriteAllBytes(path, bytes);
        }
    }
}

これを実行すると (プログラムは自分自身を上書きしようとします)、例外がスローされます:

System.IO.IOException was unhandled
Message=The process cannot access the file 'F:\TEMP\ConsoleApplication25\ConsoleApplication25\bin\Debug\ConsoleApplication25.vshost.exe' because it is being used by another process.
Source=mscorlib
StackTrace:
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.WriteAllBytes(String path, Byte[] bytes)
   at ConsoleApplication25.Program.Main() in F:\TEMP\ConsoleApplication25\ConsoleApplication25\Program.cs:line 13
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

.. これは当然のことです。ただし、 IOException のインスタンスは、ファイルが別のプロセスによって使用されていることをプログラムで検出するために使用できる信頼できる情報を提供しません。物件だけがそう言っているのですが、これは現地の文化によるので当てにできません。Message

これに対処する方法はありますか?ファイルが別のプロセスで使用されている場合は、特別なアクションを実行する必要がありますが、このケースを他の (例外的な) ケースと区別する方法が見つかりません。

4

2 に答える 2

13

この質問はこれと重複している可能性があるため、ここでの回答は受け入れられたものにかなり近いものです。ただし、確認するエラー コードにはいくつかの顕著な違いがあります。最終的に、他の質問への回答に賛成票を投じることを検討するかもしれません。

この回答のようにすることもできますが、 ERROR_SHARING_VIOLATION(0x20)を確認してください

const long ERROR_SHARING_VIOLATION = 0x20;
const long ERROR_LOCK_VIOLATION = 0x21;

//Only for .NET <4.5: long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
long win32ErrorCode = ex.HResult & 0xFFFF; // .NET 4.5+
if (win32ErrorCode == ERROR_SHARING_VIOLATION || win32ErrorCode == ERROR_LOCK_VIOLATION )
{
    // file in use.
}

ただし、使用GetHRForExceptionには望ましくない副作用があることに注意してください。

更新コメンター @jmn2 が指摘したように、.NET 4.5 以降、Exception.HResultプロパティはパブリックになりました。GetHRForExceptionもちろん、4.5より前のコードをサポートする必要がない限り、-を使用する必要はありません。

ランタイムと下位互換性のある「ラッパー」を作成するには、HResultリフレクションを介して呼び出す必要があります。これは、.NET フレームワークのすべてのバージョンで動作するためです (GetPropertiesを使用する場合) (この非常に関連する回答を参照してください)。BindingFlags.Public BindingFlags.NonPublic

于 2012-08-21T12:45:38.267 に答える
1

ここに同様の質問があります

例外の HResult を確認する必要があります。次に、その値を確認します。

int hr = Marshal.GetHRForException( ex );

ロック違反の違反を共有するためのコードは次のとおりです

于 2012-08-21T12:38:54.910 に答える