2010-04-27 97 views
3

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

我已经被赋予了保护这些方法中的每一个方法免受异常的任务(使用COM的Error()函数来捕获它们并返回一个错误,顺便说一句,我找不到任何文档,因为这是不可能的)。就我的理解而言,这要求我在这些方法的每一个的内脏周围添加一个try/catch。对于这几百种方法中的每一种来说,catch块都是相似或相同的,这些方法强烈地感染了一个问题(大量违反了DRY原则),但我想不出任何方法来避免改变每种方法。据我所知,这些方法是由COM直接调用的,没有中间代码,我可以用它来捕获异常。我目前最好的想法是为catch块创建一个宏,但它有它自己的代码嗅觉。任何人都可以想出更好的方法吗?

顺便说一下,我的应用程序的异常不会从std :: exception中派生出来,所以如果有一些COM自动处理标准异常的方法,它将无济于事。而且我很遗憾不能改变现有的从std :: exception派生的异常。

回答

3

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

定义一个用于清除IErrorInfotry {的“开始方法”宏,并为} catch和错误处理定义“结束方法”。如果你正确地设计宏 - 把除了最必要的错误处理代码之外的所有东西都放到辅助函数中,它将是一个可以容忍并且可靠的解决方案,它具有清晰的中等维护代码。

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

0

Comet是大大简化所涉及工作的一种方法。

+0

看起来很有趣,但对于这个遗留系统,我认为这将是一个不可能的巨大工作量开始使用。如果我不幸设计出一个使用COM的新系统,我会记住它。 – rmeador 2010-04-27 19:40:00

0

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

我实际上并不建议这样做,但这是一种方法,可以使执行COM对象的运行时间与外部系统绝缘。

+0

你有一个链接或示例代码如何做到这一点? C++是否允许您以这种方式修改vtable,或者您是否需要使用一些直接的内存操作?难道它不是架构和操作系统的依赖(这可能会引起我的老板“不”)? – rmeador 2010-04-27 20:05:43

3

这里没有快乐的答案。让C++或SEH异常终止COM方法是非法的。你必须必须捕捉它们并将它们翻译成合适的HRESULT。您的coclass必须实现ISupportsErrorInfo和IErrorInfo接口,以便客户端可以返回异常信息。 CLR将很快这样做来产生定制的异常消息。

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

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

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

+0

或者也许SetErrorInfo(),这很可能是ATL方法包装的。 http://msdn.microsoft.com/en-us/library/aa910593(v=MSDN.10).aspx – 2010-04-28 05:56:41