2010-10-05 43 views
0

簡短版本 我在VB.net和VSTO中有一個Word Addin,它通過Word.COMAddins.Object公開了一個COM兼容對象,這樣插件功能可以稱爲外部到Word,不需要訪問Word本身就是跨進程。當通過VB.net做Word自動化時避免跨進程調用

該技術在VB6中工作,但是與VB.net一樣,它仍然可以工作,但它比通過任務窗格直接從插件運行的代碼慢得多,就好像這些調用都是跨進程,不要。 X

長版本 該插件本質上是做噸的處理上的Word文檔。 插件可以以兩種方式運行。

  1. 從Word,使用taskpane
  2. 外部,經由一組暴露於COM類 (因爲我必須 提供到VB6客戶端應用程序訪問功能 。

但是,這裏有些磕磕碰碰。任何曾經完成過Word自動化的人都知道,使用Word執行完全可接受的INPROC的代碼(在這種情況下,Word自身加載的ADDIN的實例)通常會在進程(或跨進程)之外慢慢地運行得令人無法接受, 。

這個應用程序也沒有什麼不同。

以前,我利用一個方便的技巧來規避這個問題。

  1. 創建一個Word加載項和往常一樣
  2. 通過 Word.COMAddin.Object屬性, 讓外部代碼訪問您的 插件揭露的對象。
  3. 在你的外部項目,而不是 操縱話語直接,使用 Application.COMAddins收集, 找到你的插件,從中獲取 暴露COMAddin.Object財產 ,然後調用一個方法上 該對象,做工作。

當然,調用你的COMAddin.Object對象仍然會交叉的過程,但是,一旦執行是在與文字處理的插件,你的插件現在可以執行它想要的所有Word對象操作而且速度很快,因爲它們在那個時候都在進行中。

這工作在VB6 COM天。

但是,我放在一起這VB.net VSTO插件,並通過VSTO的連接對象的RequestComAddInAutomationService功能暴露我的插件對象

我可以打電話到我的插件外,他們都準確地工作,我期望他們除了他們都是+慢+,非常像進入Word的調用仍在執行跨進程,即使這些調用Word的代碼是由Word加載的加載項DLL的一部分!

並且以約10比1的因子減慢;當通過任務窗格直接從ADDIN運行時需要3秒的時間運行,當通過COMADDIN.object對象從外部代碼調用時需要約30秒的時間運行。

我在猜測我遇到了.net APPDOMAINS或某事的某種問題,並且在+ .net中構成了交叉處理函數,但是我沒有發現任何內容,甚至暗示了這一點那類的東西。

我的下一步,除了一些神祕的洞察力,將代碼repro,由於在場的元素的剪切數量可能會變得棘手。

有什麼想法?

+0

那麼,不是一個完美的解決方案,但我找到了+ a +解決方案。它涉及一個定時器,所以它肯定是不理想的實質上,當插件由Word加載時(即在STARTUP事件期間),初始化一個定時器(一個WINFORMS定時器,而不是一個線程定時器),並將其間隔設置爲500。外部代碼通過COMADDIN.OBject屬性連接到插件,並調用插件,設置一個變量標誌,該標誌正在被定時器輪詢。當定時器看到它被設置時,它會重置標誌並執行操作。 – DarinH 2010-10-07 21:14:50

+0

這是我發現的唯一途徑,即讓外部調用在Word的UI線程中正確執行,從而與從Word內部插件直接執行的代碼一樣快。 – DarinH 2010-10-07 21:19:35

+0

我試過使用SynchronizationContext,但我無法獲得POST或SEND以正確調用刪除我設置的交叉線程。不知道這是一個COM阻止問題,或者我只是沒有完全正確地使用synccontext。 – DarinH 2010-10-07 21:20:50

回答

0

不幸的是,Thorben提到的事件鉤子技術不適用於我的特殊情況。

所以我關閉了這個問題出來與我在評論中提到的解決方法,我會在這裏重複...

嗯,不是一個完美的解決方案,但我發現+ A +的解決方案。它涉及一個定時器,所以它絕對是次優的。實際上,當插件被Word加載時(即在STARTUP事件期間),初始化一個定時器(一個WINFORMS定時器,而不是一個線程定時器),並將其間隔設置爲500.當External代碼通過COMADDIN.OBject屬性連接到插件,並調用插件,設置一個變量標誌,該標誌正在被定時器輪詢。當定時器看到它被設置時,它會重置標誌並執行操作。

這不是我希望的乾淨解決方案,但實現起來相當簡單,事後適度易於理解,它絕對避免了將xprocess COM調用放慢到Word中的速度。

1

我做了我的VSTO Word中相同的意見加入我想添加什麼在這裏:當你把你的程序作爲一個單擊處理程序到按鈕:

`this.testButton.Click + =新Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);「

和 」YourProcedure「 實現你的昂貴的過程,你可以打電話到使用

this.testButton.Execute Word的UI線程();

這不是一個優雅的解決方案,但也許有用,如果你碰巧在CommandBar中準備好按鈕。

+0

有趣的想法。沒有嘗試過。不幸的是在我的情況下,我有很多功能來實現,沒有相應的命令欄按鈕。但是,這可能是一個知道其他用途的好方法。謝謝! – DarinH 2011-04-28 21:57:38

+0

你還可以做些什麼:只需創建一個隱藏的命令欄按鈕,將其用作單詞線程的「入口點」。在其單擊處理程序內部,您可以決定執行哪個操作(可能會將其存儲在加載項對象的成員中)並調用相應的函數。 就像定時器解決方案,但用一個按鈕代替定時器;) – 2011-04-30 20:08:22