C# 如何检查 IOException 是否为 Not-Enough-Disk-Space-Exception 类型?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9293227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 06:45:23  来源:igfitidea点击:

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

c#.netexception-handlingioexceptiondiskspace

提问by jotbek

How can I check if IOExceptionis a "Not enough disk space" exception type?

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

At the moment I check to see if the message matches something like "Not enough disk space", but I know that this won't work if the OS language is not English.

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

采纳答案by Justin

You need to check the HResultand test against ERROR_DISK_FULL (0x70)and ERROR_HANDLE_DISK_FULL (0x27), which can be converted to HResultsby OR'ing with 0x80070000.

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

For .Net Framework 4.5 and above, you can use the Exception.HResultproperty:

对于 .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;
}

For older versions, you can use Marshal.GetHRForExceptionto get back the HResult, but this has significant side-effects and is not recommended:

对于旧版本,您可以使用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;
}

From the MSDN documentation:

从 MSDN 文档:

Note that the GetHRForExceptionmethod sets the IErrorInfoof the current thread. This can cause unexpected results for methods like the ThrowExceptionForHRmethods that default to using the IErrorInfoof the current thread if it is set.

请注意,GetHRForException方法设置当前线程的IErrorInfo。这可能会导致ThrowExceptionForHR 等方法出现意外结果, 如果设置了当前线程的IErrorInfo,这些方法默认使用当前线程。

See also How do I determine the HResult for a System.IO.IOException?

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

回答by AaronHS

System.IOException has a number of derived Exception types, however none of these derived type sound like your exception. You can look at the HResult or the Data property of the exception, perhaps this will have a more specific error code detailed. According to MSDNboth those properties are part of that exception type. Just make sure you are try catching the specific exception type, not just the base Exception type.

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

回答by ken2k

Well, it's a bit hacky, but here we go.

好吧,这有点hacky,但我们开始了。

First thing to do is to get the HResultfrom the exception. As it's a protected member, we need a bit of reflection to get the value. Here's an extension method to will do the trick:

首先要做的是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);
    }
}

Now, in your catch scope, you can get the HResult:

现在,在您的捕获范围内,您可以获得HResult

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

From here, you'll have to interpret the HResult. You'll need this link.

从这里开始,您必须解释 HResult。你需要这个链接

We need to get the ErrorCodewhich is stored in the 16 first bits of the value, so here's some bit operation:

我们需要获取ErrorCode存储在值的前 16 位中的 ,所以这里有一些位操作:

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

Now, refer to the list of system error codesand here we are:

现在,参考系统错误代码列表,我们在这里:

ERROR_DISK_FULL
112 (0x70)

So test it using:

因此,使用以下方法对其进行测试:

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

Maybe there are some "higher level" functions to get all this stuff, but at least it works.

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

回答by BateTech

In .NET 4.5, the HResultproperty getter is now Public, so you do not have to use Marshal.GetHRForException(along with its side affects) anymore.

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

http://msdn.microsoft.com/en-us/library/system.exception.hresult(v=vs.110).aspxstates "Starting with the .NET Framework 4.5, the HResult property's setter is protected, whereas its getter is public. In previous versions of the .NET Framework, both getter and setter are protected"

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 都受到保护”

So you can use Justin's answer, but replace Marshal.GetHRForException(ex)with ex.HResult.

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

回答by Dominik Palo

Most simple inline solution (min .NET 4.5 and C# 6):

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

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