jot*_*bek 63 .net c# diskspace exception-handling ioexception
如何检查IOException
"磁盘空间不足"异常类型?
目前我检查消息是否与"磁盘空间不足"相匹配,但我知道如果操作系统语言不是英语,这将不起作用.
Jus*_*tin 72
你需要检查HResult
并测试ERROR_DISK_FULL(0x70)和ERROR_HANDLE_DISK_FULL(0x27),它们可以HResults
通过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;
}
Run Code Online (Sandbox Code Playgroud)
对于旧版本,您可以使用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;
}
Run Code Online (Sandbox Code Playgroud)
从MSDN文档:
请注意,GetHRForException方法设置当前线程的IErrorInfo.这可能会导致ThrowExceptionForHR方法等方法出现意外结果, 如果设置了默认使用当前线程的IErrorInfo.
另请参阅如何确定System.IO.IOException的HResult?
Bat*_*ech 21
在.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都受到保护"
所以你可以使用贾斯汀的答案,但替换Marshal.GetHRForException(ex)
为ex.HResult
.
ken*_*n2k 13
嗯,这有点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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在您的捕获范围中,您可以获得HResult
:
catch (Exception ex)
{
int hResult = ex.HResultPublic();
}
Run Code Online (Sandbox Code Playgroud)
从这里开始,你必须解释HResult.你需要这个链接.
我们需要得到ErrorCode
存储在值的16位的第一位,所以这里有一些位操作:
int errorCode = (int)(hResult & 0x0000FFFF);
Run Code Online (Sandbox Code Playgroud)
现在,请参阅系统错误代码列表,我们在这里:
ERROR_DISK_FULL
112 (0x70)
Run Code Online (Sandbox Code Playgroud)
所以测试它使用:
switch (errorCode)
{
case 112:
// Disk full
}
Run Code Online (Sandbox Code Playgroud)
也许有一些"更高级别"的功能来获得所有这些东西,但至少它是有效的.
Dom*_*alo 11
最简单的内联解决方案(min .NET 4.5和C#6):
try
{
//...
}
catch (IOException ex) when ((ex.HResult & 0xFFFF) == 0x27 || (ex.HResult & 0xFFFF) == 0x70)
{
//...
}
Run Code Online (Sandbox Code Playgroud)