通过VB.net进行Word自动化时避免跨进程调用
-
28-09-2019 - |
题
简短版本 我在VB.net和VSTO中都有一个Word插件,该插件通过Word.COMAddins.Object公开了一个COM兼容对象,因此可以将插件功能称为Word的外部功能,而无需交叉处理对Word本身的访问。
该技术在VB6中有效,但在VB.net上仍然有效,但是它比通过任务窗格直接从外接程序运行的相同代码慢得多,好像调用在不应该进行时都是跨进程的是。 x
完整版 这个插件本质上对Word文档进行了大量处理。 该插件可以通过两种方式运行。
- 在Word中使用任务窗格
- 通过一组类在外部
暴露于COM(因为我必须
提供对功能的访问
到VB6客户端应用。
但是,这是摩擦。曾经做过Word自动化的任何人都知道,与Word完美兼容的INPROC(在这种情况下为Word本身加载的ADDIN实例)运行的代码通常会在进程(或跨进程)中缓慢地运行而无法接受。
此应用没什么不同。
很久以前,我利用一个方便的技巧来规避此问题。
- 照常创建Word加载项
- 通过 Word.COMAddin.Object属性 将允许外部代码访问您的 插件。
- 在您的外部项目中,而不是
直接操作Word,使用
Application.COMAddins集合,
找到您的插件,检索
公开的COMAddin.Object属性
从它,然后调用一个方法
起作用的对象。
当然,对COMAddin.Object对象的调用仍将是跨进程的,但是,一旦在Word的IN进程中的加载项中执行,您的加载项现在就可以执行所需的所有Word对象操作,而且速度很快因为它们当时都是进程内调用。
那在VB6 COM时代就行了。
但是,我整理了这个VB.net vsto插件,并通过VSTO的Connect对象的RequestComAddInAutomationService函数公开了我的插件对象
我可以在外部对外接程序进行调用,它们的工作都完全符合我的期望,除了它们都是+ slow +之外,这很像对Word的调用仍在跨进程中执行,即使使这些代码对Word的调用是Word进程内加载的插件dll的一部分!
并且慢大约10到1的倍数;通过任务窗格直接从ADDIN运行时,需要花费3秒的时间,而通过COMADDIN.object对象从外部代码调用时,则需要30秒的时间。
我猜想我遇到了.net APPDOMAINS之类的问题,以及.net中+ really +构成交叉proc调用的原因,但到目前为止,我发现没有任何东西可以暗示这种问题事情。
除非有一些神秘的见解,否则我的下一步就是编写一个repro,由于正在播放的元素数量众多,因此可能会很棘手。
有什么想法吗?
解决方案 2
不幸的是,Thorben提到的事件挂钩技术不适用于我的特定情况。
所以我用我在评论中提到的解决方法来结束这个问题,我将在这里重复...
嗯,不是一个完美的解决方案,但是我发现了+ a +解决方案。它涉及一个计时器,因此绝对不是最佳选择。本质上,当Word加载该插件时(即在STARTUP事件期间),初始化一个计时器(WINFORMS计时器,而不是线程计时器),并将其间隔设置为500。代码通过COMADDIN.OBject属性连接到插件,并调用该插件,设置一个变量标志,该标志由计时器轮询。当计时器看到它已设置时,它将重置标志并执行操作。
这不是我想要的干净解决方案,但是它相当容易实现,事后一定程度上易于理解,并且绝对避免了xprocess COM调用Word的速度变慢。
其他提示
我使用VSTO Word插件进行了相同的观察。我想在此处添加的内容:将过程作为单击处理程序添加到按钮时:
`this.testButton.Click +=新的Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);´
并在“ YourProcedure”中实现昂贵的过程,您可以使用调用Word的UI线程
this.testButton.Execute();
这也不是一个很好的解决方案,但是如果您恰好在CommandBar中准备好按钮,则可能很有用。