如何确定System.IO.IOException的HResult?

Che*_*eso 34 .net c# exception hresult

System.Exception.HResult属性受保护.我怎样才能偷看异常并获得HResult而不诉诸于反思或其他丑陋的黑客攻击?


情况就是这样:
我想编写一个备份工具,它可以打开和读取系统上的文件.根据本指南,我使用FileAccess.Read和FileShare.ReadWrite打开文件,因为在我阅读文件时,我不在乎文件是否打开.

在某些情况下,当我读文件被打开另一个应用程序,该System.IO.FileStream.Read()方法引发System.IO.IOException,"该进程无法访问文件,因为另一个进程已锁定的一部分文件".这是错误33,或者我认为HResult 0x80070021.[ 编辑:我相信当另一个进程调用LockFileEx来锁定文件中的字节范围时,可以返回此值.]

当我收到此错误时,我想暂停并重试.我认为这是采取适当的行动.如果锁定进程快速释放字节范围锁,那么我可以继续读取该文件.

出于这个原因,我如何区分IOException?我可以想到这些方法:

  • 私人反思 - 不想那样做.Perf会发臭.
  • 调用Exception.ToString()并解析字符串.感觉hacky.在i18n版本中不起作用.

我不喜欢这些选择.是不是有更好,更清洁的方式?


我只是搜索并找到System.Runtime.InteropServices.Marshal.GetHRForException.那将返回像0x80070021这样的uint吗?

Jar*_*Par 56

对于.Net Framework 4.5及更高版本,您可以使用以下Exception.HResult属性:

int hr = ex.HResult;
Run Code Online (Sandbox Code Playgroud)

对于旧版本,您可以使用Marshal.GetHRForException以获取HResult,但这具有显着的副作用,不建议使用:

int hr = Marshal.GetHRForException(ex);
Run Code Online (Sandbox Code Playgroud)

  • 注意副作用:"请注意,**GetHRForException**方法设置当前线程的**IErrorInfo**.这可能会导致**ThrowExceptionForHR**方法默认使用**的方法出现意外结果如果设置了当前线程的IErrorInfo**." (3认同)
  • +1 Eww,需要完全信任......但它仍然是一个解决方案. (2认同)

Uwe*_*ayr 11

对于它的价值,System.Exception.HResult在.NET 4.5中不再受保护 - 只有setter受到保护.这对可能使用多个版本的框架编译的代码没有帮助.


Max*_*nce 5

您还可以使用该ISerializable接口:

static class IOExceptionExtensions
{
    public static int GetHResult(this IOException ex)
    {
        var info = new SerializationInfo(typeof (IOException), new FormatterConverter());
        ex.GetObjectData(info, new StreamingContext());
        return info.GetInt32("HResult");
    }
}
Run Code Online (Sandbox Code Playgroud)