【问题标题】:CoInitializeEx() with COINIT_APARTMENTTHREADED or COINIT_MULTITHREADED for MS-Word automation using COM C++CoInitializeEx() 和 COINIT_APARTMENTTHREADED 或 COINIT_MULTITHREADED 用于使用 COM C++ 的 MS-Word 自动化
【发布时间】:2021-11-16 12:35:13
【问题描述】:

我正在尝试使用 MS-Word 自动化某个场景,我希望在启动打印时获取 BeforePrint 事件以获取文件路径。完成这项工作所需的技术是 COM C++。我通过在启动时附加到字处理来初始化 COM 库,通过使用 COINIT_APARTMENTTHREADED 调用 CoInitializeEx() 并且一切正常。但是,当启动另一个执行类似操作的应用程序时,例如,从 Adob​​e Acrobat DC 中的 word 或任何对 BeforePrint 事件执行某些操作的 office 插件创建 pdf,应用程序/插件的功能会出错。我的预感是 COM 的初始化方式有问题,因为如果我通过使用 COINIT_MULTITHREADED 调用 CoInitializeEx() 来初始化 COM,一切似乎都可以正常工作。 以下是这方面的具体问题:

  1. 使用 COINIT_APARTMENTTHREADED 和 COINIT_MULTITHREADED 调用 CoInitializeEx() 有什么不同使其在这种情况下工作?
  2. 对于 Word 的 COM C++ 办公自动化的大多数在线示例,CoInitializeEx() 是使用 COINIT_APARTMENTTHREADED 完成的,推荐的方法是什么?为什么?
  3. 如果我的应用程序对 CoInitializeEx() 使用 COINIT_MULTITHREADED 而不是 COINIT_APARTMENTTHREADED,任何其他应用程序/office 插件会不会出现问题?

我已经提到但不够明确的链接: https://docs.microsoft.com/en-us/visualstudio/vsto/threading-support-in-office?view=vs-2019 https://docs.microsoft.com/en-us/windows/win32/api/objbase/ne-objbase-coinit

【问题讨论】:

  • 有关于这个主题的完整书籍。抱歉,您的问题过于宽泛,无法在此处简明准确地回答。
  • 我同意有很多可用的书籍和在线示例,我已经参考并获得了关于这个主题的这里。该问题针对 ms-word 和 BeforePrint 事件自动化,并针对已注意到的观察提出针对性问题。请帮助建议/询问有关缩小范围所需的更多详细信息的问题。谢谢!
  • 请编辑问题以将其限制为具有足够详细信息的特定问题,以确定适当的答案。

标签: c++ com office-js office-addins


【解决方案1】:

当您在 STA 线程上创建 COM 对象时,所有传入和传出 COM 调用都将从 Windows 消息队列中处理。来自对象的事件处理程序 事件也将使用该消息队列,因此将在创建 COM 对象的同一 STA 线程上调用事件处理程序。但是,您不能做的一件事是从事件处理程序对该对象进行其他 COM 调用! (谷歌:COM STA 重入)。

当您在 MTA 线程上创建 COM 对象时,事件也将由 MTA 线程(来自 COM 线程池)处理,并且不会发生重入,您可以从事件处理程序调用对象。这种情况比较稳定,但是如果你需要与主线程(例如MainWindow)交互,你必须自己编写一些代码。

最后,我更喜欢 MTA,即使您必须自己管理一些跨线程通信,它们也不会那么混乱。但至少它是明确的。

【讨论】:

    猜你喜欢
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 2017-07-14
    • 1970-01-01
    相关资源
    最近更新 更多