2011-05-13 54 views
1

我正在使用com-interop在c#中使用com对象。我为对象提供了一个事件处理程序,它在完成它的事情后调用它。这是问题。我在抛出异常的处理一些理智检查代码,如果一切都没有很好地与世界:来自COM事件处理程序的错误通知,使用互操作

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

    ... 
} 

COM对象显然是吞咽那些例外,因为我从来没有看到他们在我的应用程序。我需要做些什么来“表面”这些例外情况,以便在发生这种情况时得到通知?

回答

1

你可以使用Application.Current.Dispatcher.Invoke()方法,通过提供一个代理来抛出你的异常。

3

如果事件由COM服务器引发,这不是意外的行为。异常不允许跨越COM分歧,对于异常没有二进制互操作标准。 CLR在它的interop层安装一个catch-all异常处理程序,这是调用你的事件处理程序的代码。您提出的异常会转换为HRESULT,这是COM代码报告失败的标准方式。对于通用的Exception对象,这将是0x80131500。

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

如果可能的话,与COM组件供应商或作者一起工作。这种情况并不常见。除了记录失败之外,你可以做的事情并不多。调用Environment.Exit()如果这是一个不可能被忽略的严重问题。这与您的程序以未处理的异常终止并没有任何区别。

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服务器,你可以调用错误,并且在这个例子中,传递EXCEPINFO作为第七参数来调用。它将包含.NET异常文本“这是疯了!!!”。

相关问题