繁体   English   中英

如何检查IOException是否足够 - 磁盘空间异常类型?

[英]How to check if IOException is Not-Enough-Disk-Space-Exception type?

如何检查IOException是否为“磁盘空间不足”异常类型?

目前我检查消息是否与“磁盘空间不足”相匹配,但我知道如果操作系统语言不是英语,这将不起作用。

您需要检查HResult并针对ERROR_DISK_FULL(0x70)ERROR_HANDLE_DISK_FULL(0x27)进行测试可以通过OR0x80070000将其转换为HResults

对于.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 这可能会导致ThrowExceptionForHR方法等方法出现意外结果,如果设置了默认使用当前线程的IErrorInfo

另请参阅如何确定System.IO.IOException的HResult?

在.NET 4.5中, HResult属性getter现在是Public,因此您不必再使用Marshal.GetHRForException (及其副作用)。

http://msdn.microsoft.com/en-us/library/system.exception.hresult(v=vs.110).aspx声明“从.NET Framework 4.5开始,HResult属性的setter受到保护,而其getter在以前版本的.NET Framework中,getter和setter都受到保护“

所以你可以使用Justin的答案,但用ex.HResult替换Marshal.GetHRForException(ex)

嗯,这有点hacky,但我们走了。

首先要做的是从异常中获取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
}

也许有一些“更高级别”的功能来获得所有这些东西,但至少它是有效的。

最简单的内联解决方案(min .NET 4.5和C#6):

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

System.IOException有许多派生的Exception类型,但是这些派生类型中没有一个听起来像你的异常。 您可以查看异常的HResult或Data属性,也许这将具有更详细的更具体的错误代码。 根据MSDN ,这些属性都是该异常类型的一部分。 只需确保您尝试捕获特定的异常类型,而不仅仅是基本的异常类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM