从非托管代码挂钩到AppDomain.UnhandledException事件

时间:2011-03-24 12:04:59

标签: c++ events hosting clr

我有一个CLR托管应用程序,用非托管C ++编写。 我想从非托管C ++代码订阅AppDomain.UnhandledException事件。

导入的AppDomain接口具有以下方法:

HRESULT add_UnhandledException (struct _UnhandledExceptionEventHandler *value);

UnhandledExceptionEventHandler定义为:

struct __declspec(uuid("84199e64-439c-3011-b249-3c9065735adb"))
_UnhandledExceptionEventHandler : IDispatch {}; 

我不明白如何使用此处理程序将其连接到我的回调函数。 那么,问题是如何使用它?

1 个答案:

答案 0 :(得分:2)

我没有看到有人这样做,但它可能会帮助您考虑以下事项:

  1. 托管delagate不是c ++中的“简单”回调,它继承自clr-object,我在c ++中看到的代码挂钩事件始终是托管c ++。
  2. 触发未处理的异常处理程序后,接下来发生的事情取决于clr策略设置(参见3.)
    1. 流程终止(默认)
    2. appdomain已卸载
    3. 或clr已停用
    4. 吞下异常(.net 1.x中clr的行为)
  3. 您可以通过IHostPolicyManager
  4. 将默认操作更改为2.2,2.3,2.4
  5. 假设您将策略设置为卸载或禁用,您可以使用IActionOnCLREvent在卸载/禁用时设置回调。
  6. 3)和4)您可以设置您的系统
    1. 在UnhandledExceptionHandler中的托管代码中清理/记录/保存(您需要的任何内容)
    2. 您会收到有关在非托管代码中卸载appdomain的通知...并执行您仍需执行的操作。
  7. 假设这还不够(你的非托管代码需要知道异常的一些细节)你可以定义com接口(参见下面的idl示例);当您设置appnmain并传入非托管实现IMypplicationSink(您的钩子)时,托管应用程序实现IMyApplication和非托管代码IMyApplicationSink,托管应用程序必须在托管unhandledexception事件处理程序中调用该钩子:

    interface IMyApplicationSink : IUnknown
    {
        HRESULT UnhandeledExceptionCallback(
        [in] BSTR aString,
        [in] short aNumber,
        [in] SAFEARRAY( BYTE ) someBinaryData);
    }
    
    interface IMyApplicationControl : IUnknown
    {
        HRESULT OnStart(
        [in] IPhotonApplicationSink *sink);
    }
    

    注意:有关如何获取自定义com接口的详细信息,请参阅“自定义Microsoft .NET Framework公共语言运行时”的“实现IHostControl :: SetAppDomainManager”(当前部分可自由阅读here

  8. 如果您无法控制托管应用程序,请首先加载您控制中的应用程序 - 默认应用程序域 - 也将在那里调用未处理的异常处理程序(请参阅msdn

  9. 如果您将策略设置为吞咽(2.4),则不会通知您的非托管代码clr将继续运行 - 您当然可以将其与自定义com接口(6。)结合使用。