保护COM接口不受异常影响

时间:2010-04-27 19:28:45

标签: c++ exception com exception-handling

我有几十个通过COM接口公开的对象,每个对象都有很多方法,总共有几百个方法。这些接口将业务对象从我的应用程序暴露给脚本引擎。

我的任务是保护这些方法中的每一个都不被抛出异常(捕获它们并使用COM的Error()函数返回错误,顺便说一句,我找不到任何文档,因为它是不可能的谷歌)。据我所知,这要求我在每个方法的内容周围添加一个try / catch。对于这些数百种方法中的每一种,捕获块都是相似或相同的,这些方法强烈地存在问题(严重违反DRY原则),但我想不出任何方法可以避免改变每种方法。据我所知,这些方法是由COM直接调用的,没有中间代码可以挂钩来捕获异常。我目前最好的想法是为catch块创建一个宏,但它有它自己的代码味道。任何人都可以提出更好的方法吗?

BTW,我的应用程序的异常不是从std :: exception派生的,所以如果有一些COM自动处理标准异常的方法,它将无济于事。我遗憾地无法改变从std :: exception派生的现有异常。

4 个答案:

答案 0 :(得分:3)

这里没有快乐的答案。让C ++或SEH异常终止COM方法是违法的。您必须捕获它们并将它们转换为适当的HRESULT。您的coclass必须实现ISupportsErrorInfo和IErrorInfo接口,以便客户端可以获取异常信息。 CLR很容易这样做以产生定制的异常消息。

你说的Error()方法很可能是ATL CComCoClass::Error() method。它设置了IErrorInfo将返回的异常信息。

没有机制来注入单个try / catch块来捕获所有可能的异常,COM方法直接从客户端调用。您必须为每个调用可引发异常的C ++代码的COM方法执行此操作。令人不快,但这应该是在编写代码时完成的。你可能需要包装它们中的每一个,因为现在发现它是否正在调用可能抛出的代码是很困难的。

从技术上讲,你可以改变类工厂来创建一个包装器,一个实现接口的每个方法并委托给实际方法的包装器。使用样板试用/捕获处理程序。很机械,你可以想出一些宏来减轻打击。

答案 1 :(得分:3)

最可靠的C ++方法是在这里使用宏。我已经准备好接受这个说法,但我们多年来一直在使用这个解决方案,到目前为止还没有看到任何严重的问题。

定义“开始方法”宏,用于清除IErrorInfo的{​​{1}}和try {以及“结束方法”以及错误处理。如果您正确地设计宏 - 将除了最必要的错误处理代码之外的所有代码放入辅助函数中,那么它将是一个可以容忍且可靠的解决方案,具有干净的中等可维护代码。

是的,那是doesn't look good at all,但至少它是实现你想要的可靠和符合标准的方式。

答案 2 :(得分:0)

Comet是大大简化相关工作的一种方法。

答案 3 :(得分:0)

鉴于所有COM接口方法都使用__stdcall约定并假设您可以自己创建COM对象,您可以“简单地”创建一个包装COM对象,该对象通过{{1}返回一个包装的COM接口}。这个包装的COM接口应该是一个COM接口,其中每个vtable条目都被一个用QueryInterface包装原始vtable函数的thunk替换。

我实际上并不建议这样做,但这是一种可以隔离从外部系统实现COM对象的运行时的方法。