我正在使用com-interop在c#中使用com对象。我为对象提供了一个事件处理程序,它在执行它之后调用它。这是问题所在。我在处理程序中有一些健全性检查代码,如果一切都与世界不符,则抛出异常:
_comObj.OnRequestCompleted += (int requestID, RequestStatus status) =>
{
if (<sanity check fails>)
throw new Exception("This is insane!!!");
...
}
com对象显然吞下了这些异常,因为我从来没有在我的应用中看到它们。我需要做些什么来“表达”这些例外情况,以便在发生时通知我?
答案 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, ¶ms, &varResult, NULL, NULL);
}
return hr;
}
因此,hr
确实包含错误代码,但一般来说,COM服务器实现者只是
Fire_MyCustomEvent()
因为通常可以有多个来电者。如果一个来电失败,你会怎么做?大家都失败了在一般情况下,没有。请参阅此处有关类似主题的有趣讨论:Observers Should Never Throw Exceptions
也就是说,如果你拥有COM服务器,你可以捕获Invoke错误,在这个例子中,传递EXCEPINFO作为第7个参数来调用。它将包含.NET Exception文本“This is insane !!!”。