【问题标题】:protecting COM interfaces from exceptions保护 COM 接口免受异常影响
【发布时间】:2010-04-27 19:28:45
【问题描述】:

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

我的任务是保护这些方法中的每一个不被抛出异常(捕获它们并使用 COM 的 Error() 函数返回错误,顺便说一下,我找不到任何文档,因为它不可能通过谷歌搜索) .据我了解,这需要我在每个方法的核心周围添加一个 try/catch。对于这数百种方法中的每一种,catch 块都将是相似或相同的,这强烈地嗅到了问题的味道(严重违反了 DRY 原则),但我想不出任何方法来避免更改每种方法。据我所知,这些方法是由 COM 直接调用的,没有可以用来捕获异常的干预代码。我目前最好的想法是为 catch 块制作一个宏,但这有它自己的代码味道。谁能想出更好的方法?

顺便说一句,我的应用程序的异常不是从 std::exception 派生的,所以如果 COM 有某种方式自动处理标准异常,那将无济于事。遗憾的是,我无法将现有异常更改为从 std::exception 派生。

【问题讨论】:

    标签: c++ exception com exception-handling


    【解决方案1】:

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

    定义用于清除IErrorInfotry { 的“开始方法”宏和用于} catch 的“结束方法”以及错误处理。如果您正确设计宏 - 将除最必要的错误处理代码之外的所有代码放入辅助函数中,这将是一个可容忍且可靠的解决方案,代码看起来干净且可适度维护。

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 这看起来很有趣,但是对于这个遗留系统,我认为开始使用这将是一项不可能完成的大量工作。如果我不幸设计了一个使用 COM 的新系统,我会记住这一点。
      【解决方案4】:

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

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

      【讨论】:

      • 您有如何执行此操作的链接或示例代码吗? C++ 是否允许您以这种方式修改 vtable,或者您是否必须使用一些直接的内存操作?而且它不会依赖于架构和操作系统(这可能会引起我老板的“不”)?
      猜你喜欢
      • 2016-05-14
      • 2017-03-28
      • 1970-01-01
      • 2015-11-19
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2018-07-24
      相关资源
      最近更新 更多