System.Runtime.InteropServices.GetHRForException的陷阱

从字面上看,GetHRForException函数的作用很简单:得到Exception所对应的HRESULT的值。但是,GetHRForException还会做一件事情:设置当前线程的IErrorInfo使之指向该Exception(严格来说是获得Exception的CCW中的IErrorInfo接口指针)。如果对IErrorInfo不熟悉的朋友们可以把IErrorInfo看成COM版本的GetLastError或者errno。设置IErrorInfo会导致之后的代码如果使用GetErrorInfo查询IErrorInfo的值,会获得一个非0的结果,那么有些代码可能会认为程序出错而拒绝继续执行。更糟糕的是,如果之后的代码在做COM Interop或者PInvoke,CLR会检查IErrorInfo,如果IErrorInfo非0则认为该调用失败,并抛出异常或者返回错误值(视乎PreserveSigAttribute是否存在)。直接的结果是可能函数调用成功,但是因为IErrorInfo已经被设置而导致该调用最终失败。很有意思的是在.NET中有一段处理资源的代码正好有这个问题,结果间接导致了巴西葡萄牙语版本(是的,你没看错J)的.NET的RegAsm挂掉。其实我个人认为这个函数应该被命名为GetHRForExceptionAndSetIErrorInfo(Exception ex);虽然有些长,但是很清晰,总比简短而错误的名字要来的好。

在正常情况下,如果你需要获得Exception的HRESULT值,应该直接使用Exception.HResult属性。那么什么时候才应该使用GetHRForException呢?当你写了一个.NET的函数准备让非托管代码调用(最好是通过COM),并且返回一个HRESULT,这个时候你有必要把托管函数内部抛出的异常转换为HR,并且把Exception本身的信息设置到当前线程的IErrorInfo中去,这才是最符合COM规范的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值