来自COM事件处理程序的错误通知,使用互操作

时间:2011-05-13 19:21:27

标签: c# com com-interop

我正在使用com-interop在c#中使用com对象。我为对象提供了一个事件处理程序,它在执行它之后调用它。这是问题所在。我在处理程序中有一些健全性检查代码,如果一切都与世界不符,则抛出异常:

_comObj.OnRequestCompleted += (int requestID, RequestStatus status) =>
{
    if (<sanity check fails>)
        throw new Exception("This is insane!!!");

    ...
}

com对象显然吞下了这些异常,因为我从来没有在我的应用中看到它们。我需要做些什么来“表达”这些例外情况,以便在发生时通知我?

3 个答案:

答案 0 :(得分:3)

如果COM服务器引发了该事件,则这不是意外行为。不允许例外超过COM划分,例外没有二进制互操作标准。 CLR在其互操作层中安装了一个catch-all异常处理程序,该代码调用您的事件处理程序。您引发的异常将转换为HRESULT,这是COM代码报告失败的标准方式。对于一般的异常对象,这将是0x80131500。

接下来发生的事情完全取决于COM服务器,它需要对它所获得的HRESULT做一些有用的事情。没有看到它做任何事情并不是非常意外,函数调用返回值经常被忽略,尤其是通知样式调用。你肯定不会得到类似管理异常的任何东西。

如果可能,与COM组件供应商或作者合作以解决问题。这种情况并非经常发生。除了记录故障之外,您无能为力。如果这是一个无法忽略的严重问题,请调用Environment.Exit()。这与使用未处理的异常终止程序没有任何不同。

答案 1 :(得分:1)

您可以使用Application.Current.Dispatcher.Invoke()方法,提供一个抛出异常的委托。

答案 2 :(得分:0)

如果你看一下所有Visual Studio版本生成的标准C ++ COM服务器实现(你使用这样的向导得到的结果:ATL Tutoral Step 5: Adding an Event),用于引发事件的C ++代码(命名为“连接点”) “在COM术语中”看起来像这样。

HRESULT Fire_MyCustomEvent()
{
  ...
  for (int iConnection = 0; iConnection < cConnections; iConnection++)
  {
      CComVariant varResult;
      DISPPARAMS params = { NULL, NULL, 0, 0 };
      hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
  }
  return hr;
}

因此,hr确实包含错误代码,但一般来说,COM服务器实现者只是

Fire_MyCustomEvent()

因为通常可以有多个来电者。如果一个来电失败,你会怎么做?大家都失败了在一般情况下,没有。请参阅此处有关类似主题的有趣讨论:Observers Should Never Throw Exceptions

也就是说,如果你拥有COM服务器,你可以捕获Invoke错误,在这个例子中,传递EXCEPINFO作为第7个参数来调用。它将包含.NET Exception文本“This is insane !!!”。