我有一个 .NET 程序集,它是通过 COM Interop 从 Delphi 主机调用的。 据我所知,.NET 代码中任何未处理的异常都将由 .net com 互操作框架处理,并且相应的 HRESULT 将返回到 COM 主机(delphi)。然而,在此异常到 HRESULT 转换期间,堆栈信息会丢失。
问题是我们希望在 .net 代码中记录所有未处理的异常,但我还没有找到任何方法来注册一个捕获所有处理程序,只要发生此类异常,就会实际调用该处理程序。
我已经尝试过:
- AppDomain.CurrentDomain.UnhandledException
- Dispatcher.CurrentDispatcher.UnhandledException
但是在 COM Interop 下运行时不会调用这些。
是否可以为 COM 互操作框架的未处理异常定义某种处理程序/回调?或者以某种方式 Hook 将托管异常转换为 HRESULT 的过程,以便可以记录异常?
谢谢!
最佳答案
我认为最好的选择是使用类似的东西
void ComClassMethod()
{
try { ... }
catch (Exception ex)
{
/* store the ex in the object */;
throw;
}
}
C# 方法中的任何地方都暴露给 COM。
或者,您可以处理 AppDomain.CurrentDomain.FirstChanceException
并存储最后一次机会异常,您也可以将其公开给 COM。
但是,请特别注意您的 COM 对象是否支持多线程(注意,大多数 .NET COM objects are free-threaded )。在这种情况下,您需要维护线程及其相应的最新异常之间的映射,无论是每个对象还是通过 System.Threading.ThreadLocal<T>
全局维护。 (决定什么更适合您的日志记录要求)。
已更新,我一直在想,必须有更好的方法来做到这一点。确实有一个,如 explained here Adam Nathan 的优秀著作《.NET 和 COM:完整的互操作性指南》一书中。我不确定我是否可以复制/粘贴受版权保护的 Material 中的准确引用,但想法如下:
- 所有 .NET CCW 对象均实现
ISupportErrorInfo
. - 扩展错误信息 - 通过
IErrorInfo
对象 - 可以通过GetErrorInfo
在 COM 端检索API。 - 根据 Adam Nathan 的说法,该对象也是 .NET 异常对象本身,并且它实现了
_Exception
COM接口(interface)。 - COM 客户端可以使用
_Exception
获取所有详细信息,包括_Exception.StackTrace
.
这似乎正是您正在寻找的东西。
关于.NET COM 互操作 -> 全局异常处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28820567/