web-dev-qa-db-ja.com

IOExceptionがNot-Enough-Disk-Space-Exceptionタイプであるかどうかを確認するにはどうすればよいですか?

IOExceptionが「ディスク容量不足」例外タイプであるかどうかを確認するにはどうすればよいですか?

現時点では、メッセージが「ディスク容量が不足しています」などと一致するかどうかを確認しますが、OS言語が英語でない場合、これが機能しないことを知っています。

61
jotbek

HResultを確認し、 ERROR_DISK_FULL(0x70) および ERROR_HANDLE_DISK_FULL(0x27) をテストする必要があります。これは HResults by OR 'ing with 0x80070000

.Net Framework 4.5以降では、Exception.HResultプロパティ:

static bool IsDiskFull(Exception ex)
{
    const int HR_ERROR_HANDLE_DISK_FULL = unchecked((int)0x80070027);
    const int HR_ERROR_DISK_FULL = unchecked((int)0x80070070);

    return ex.HResult == HR_ERROR_HANDLE_DISK_FULL 
        || ex.HResult == HR_ERROR_DISK_FULL;
}

古いバージョンでは、 Marshal.GetHRForException HResultを取得しますが、これは 重大な副作用があり推奨されません

static bool IsDiskFull(Exception ex)
{
    const int ERROR_HANDLE_DISK_FULL = 0x27;
    const int ERROR_DISK_FULL = 0x70;

    int win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
    return win32ErrorCode == ERROR_HANDLE_DISK_FULL || win32ErrorCode == ERROR_DISK_FULL;
}

MSDNドキュメントから:

GetHRForExceptionメソッドは、現在のスレッドのIErrorInfoを設定することに注意してください。これにより、現在のスレッドのIErrorInfoが設定されている場合にデフォルトで使用される ThrowExceptionForHR メソッドなどのメソッドで予期しない結果が生じる可能性があります。 。

System.IO.IOExceptionのHResultを確認する方法 も参照してください。

73
Justin

.NET 4.5では、HResultプロパティゲッターがパブリックになったため、_Marshal.GetHRForException_を(その副作用に加えて)使用する必要がなくなりました。

http://msdn.Microsoft.com/en-us/library/system.exception.hresult(v = vs.110).aspx 「.NET Framework 4.5以降、HResultプロパティのセッターは保護されていますが、そのゲッターはパブリックです。以前のバージョンの.NET Frameworkでは、ゲッターとセッターの両方が保護されています。

したがって、ジャスティンの答えを使用できますが、Marshal.GetHRForException(ex)を_ex.HResult_に置き換えます。

20
BateTech

まあ、それは少しハッキーですが、ここに行きます。

最初に行うことは、例外からHResultを取得することです。保護されたメンバーであるため、値を取得するには少し反映する必要があります。トリックを行うための拡張メソッドは次のとおりです。

public static class ExceptionExtensions
{
    public static int HResultPublic(this Exception exception)
    {
        var hResult = exception.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(z => z.Name.Equals("HResult")).First();
        return (int)hResult.GetValue(exception, null);
    }
}

これで、キャッチスコープでHResultを取得できます。

catch (Exception ex)
{
    int hResult = ex.HResultPublic();
}

ここから、HResultを解釈する必要があります。 このリンク が必要です。

値の最初の16ビットに格納されているErrorCodeを取得する必要があるため、ここでいくつかのビット操作を示します。

int errorCode = (int)(hResult & 0x0000FFFF);

ここで、 システムエラーコードのリスト を参照してください。

ERROR_DISK_FULL
112 (0x70)

以下を使用してテストします。

switch (errorCode)
{
    case 112:
        // Disk full
}

たぶん、これらすべてを取得するためのいくつかの「より高いレベルの」関数がありますが、少なくともそれは動作します。

13
ken2k

最も単純なインラインソリューション(最小.NET 4.5およびC#6):

try
{
    //...
}
catch (IOException ex) when ((ex.HResult & 0xFFFF) == 0x27 || (ex.HResult & 0xFFFF) == 0x70)
{
    //...
}
10
Dominik Palo

System.IOExceptionには多くの派生例外タイプがありますが、これらの派生タイプは例外のように聞こえません。例外のHResultまたはDataプロパティを見ることができます。これには、より詳細なエラーコードが含まれている可能性があります。 [〜#〜] msdn [〜#〜] によれば、これらのプロパティは両方ともその例外タイプの一部です。ベースの例外タイプだけでなく、特定の例外タイプをキャッチしようとしていることを確認してください。

1
AaronHS