简体   繁体   English

通过VB.net进行Word自动化时避免跨进程调用

[英]Avoiding cross process calls when doing Word automation via VB.net

The short version I've got a Word Addin in VB.net and VSTO that exposes a COM compatible object via Word.COMAddins.Object, so that the addin functionality can be called External to Word, without accesses to Word itself being cross-process. 简短版中,我在VB.net和VSTO中有一个Word插件,该插件通过Word.COMAddins.Object公开了一个COM兼容对象,因此可以将插件功能称为Word的外部,而无需交叉访问Word本身。

The technique worked in VB6, but with VB.net, it still works, but it's much slower than the same code running directly from the addin via a task pane, as if the calls are all cross process when they shouldn't be. 该技术在VB6中有效,但在VB.net上仍然有效,但是它比通过任务窗格直接从外接程序运行的相同代码慢得多,好像调用在不需要时都是跨进程的。 x X

The Long version This addin essentially does tons of processing on Word Documents. Long版本此插件实质上对Word文档进行了大量处理。 The addin can be run in two ways. 该插件可以通过两种方式运行。

  1. from within Word, using a taskpane 在Word中,使用任务窗格
  2. externally, via a set of classes exposed to COM (because I have to provide access to the functionality to VB6 client apps. 在外部,通过暴露给COM的一组类(因为我必须提供对VB6客户端应用程序功能的访问。

BUT, here's the rub. 但是,这是摩擦。 Anyone who's ever done Word automation knows that code that runs perfectly acceptably INPROC with Word (in this case the instance of the ADDIN that Word itself loads), will generally run unacceptably slowly out of process (or cross process). 曾经做过Word自动化的任何人都知道,与Word完美兼容的INPROC(在本例中为Word本身加载的ADDIN实例)运行的代码通常会在进程(或跨进程)中缓慢地运行而无法接受。

This app is no different. 这个程序没有什么不同。

Ages ago, I made use of a handy trick to circumvent this issue. 以前,我利用方便的技巧来规避此问题。

  1. Create a Word Addin as usual 照常创建Word插件
  2. Expose an object via the Word.COMAddin.Object property that will let external code access your addin. 通过Word.COMAddin.Object属性公开一个对象,该属性将允许外部代码访问您的插件。
  3. In your external project, instead of manipulating Word directly, Use the Application.COMAddins collection, find your addin, retrieve the exposed COMAddin.Object property from it and then call a method on that object that does the work. 在您的外部项目中,而不是直接操作Word,请使用Application.COMAddins集合,找到您的外接程序,从中检索公开的COMAddin.Object属性,然后在该对象上执行工作的方法。

Of course, the call to your COMAddin.Object object will still be cross process, BUT, once execution is in the addin that is IN PROCESS with Word, your addin can now perform all the Word object manipulations it wants and it's fast because they're all in-process calls at that point. 当然,对COMAddin.Object对象的调用仍将是跨进程的,但是,一旦在Word中使用IN PROCESS的加载项中执行,您的加载项现在就可以执行所需的所有Word对象操作,并且操作很快,因为它们那时所有正在进行的调用。

That worked in the VB6 COM days. 在VB6 COM时代就可以使用。

But, I put together this VB.net vsto addin, and expose my addin object via the RequestComAddInAutomationService function of VSTO's Connect object 但是,我整理了这个VB.net vsto插件,并通过VSTO的Connect对象的RequestComAddInAutomationService函数公开了我的插件对象

I can make calls into my addin externally and they all work exactly as I would expect them to, except they're all +slow+, very much like the calls into Word are still being performed cross process even though the code making those calls to Word is part of the addin dll that was loaded in-process by Word! 我可以在外部对外接程序进行调用,并且它们都完全按照我的预期工作,除了它们都是+ slow +之外,这非常像对Word的调用仍在跨进程中执行,即使对这些Word进行调用的代码也是如此是Word进程内加载的插件dll的一部分!

And slow as in a factor of about 10 to 1; 速度大约是10:1。 what takes 3 seconds to run when run directly from the ADDIN via the task pane, takes ~30seconds to run when called from external code through the COMADDIN.object object. 通过任务窗格直接从ADDIN运行时,要花3秒才能运行,而通过COMADDIN.object对象从外部代码调用时,要花30秒才能运行。

I'm guessing that I'm running into some sort of issue with .net APPDOMAINS or something and what +really+ constitutes cross proc calls in .net, but I've found nothing so far that would even hint about this sort of thing. 我猜想我遇到了.net APPDOMAINS之类的问题,以及+ .really +构成了.net中的交叉proc调用,但是到目前为止,我发现没有任何东西甚至可以暗示这种事情。

My next step, barring some mystical insight, will be to code up a repro, which could get tricky because of the shear number of elements in play. 除非获得一些神秘的见解,我的下一步是编写一个repro,由于正在播放的元素数量众多,因此可能会很棘手。

Any thoughts? 有什么想法吗?

I've made the same observations with my VSTO Word add in. What I'd like to add here: When you add your procedure as a click handler to a button: 我使用VSTO Word插件进行了相同的观察。我想在此处添加的内容:将过程作为单击处理程序添加到按钮时:

`this.testButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);´ `this.testButton.Click + =新的Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);´

and implement your expensive procedure in "YourProcedure", you can call into Word's UI thread using 并在“ YourProcedure”中实现昂贵的过程,则可以使用以下命令调用Word的UI线程

this.testButton.Execute(); this.testButton.Execute();

This is not an elegant solution either, but maybe useful if you happen to have buttons ready in a CommandBar. 这也不是一个很好的解决方案,但是如果您恰好在CommandBar中准备好按钮,则可能很有用。

Unfortunately, the Event hook technique Thorben mentions wouldn't work for my particular situation. 不幸的是,Thorben提到的事件挂钩技术不适用于我的特殊情况。

So I'm closing this question out with the workaround that I mentioned in comments and I'll repeat here... 因此,我将用我在评论中提到的解决方法来结束这个问题,在此重复我的步骤...

Well, not a perfect solution, but I have found +a+ solution. 好吧,这不是一个完美的解决方案,但我发现了+ a +解决方案。 It involved a timer, so it's definitely suboptimal Essentially, when the addin is loaded by Word, (ie during the STARTUP event), initialize a timer (a WINFORMS timer, not a threading timer), and set it's interval to 500. When External code connects to the addin via the COMADDIN.OBject property, and makes a call into the addin, set a variable flag, which is being polled by the timer. 它涉及一个计时器,因此绝对不是最佳选择。本质上,当Word加载该插件时(即在STARTUP事件期间),初始化一个计时器(WINFORMS计时器,而不是线程计时器),并将其间隔设置为500。代码通过COMADDIN.OBject属性连接到插件,并调用插件,设置一个变量标志,该标志由计时器轮询。 When the timer sees it set, it resets the flag and performs the action. 当计时器看到它已设置时,它将重置标志并执行操作。

It's not the clean solution I'd have preferred, but it's fairly easy to implement, moderately easy to understand after the fact, and it definitely avoids the slowdown of xprocess COM calls into Word. 这不是我想要的干净解决方案,但是它相当容易实现,事后一定程度上易于理解,并且绝对避免了xprocess COM调用Word的速度变慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM