2016-02-23 34 views
0

幾乎在所有情況下都會創建新的VSTO Word應用程序。我用這行來創建一個新的實例:創建VSTO Word應用程序時的問題

var wordApplication = new Application {Visible = false} 

(應用程序是「Microsoft.Office.Interop.Word.Application」)

我們做了很多的單元測試,在一些自動化。但在大約1000次調用中會出現一次或兩次,初始化沒有最終確定,並且進程掛起。 (任何人都知道的原因?)

爲了解決這個問題我換了實例爲超時,然後再次嘗試:

var wordApplication = Utilities.CallWithTimeout(
    // stuff to do 
    () => new Application {Visible = false}, 

    // error handler before the TimeoutException happens 
    () => 
    { 
     var info = "Try to create a WordApplication failed after 15 seconds"; 
     Tracer.TraceEvent(TraceEventType.Error, info, TraceCategory.Application); 
     KillWordApplicationOnError(before); 
    }, 

    // timeout 
    TimeSpan.FromSeconds(15)); 

(CallWithTimeout:https://gist.github.com/JuergenGutsch/219e9fe3e5aad1a098f3https://gist.github.com/JuergenGutsch/b4b72fcb6a06327a6a41重試是用這種方法做)

我們通過識別單詞進程並殺死該進程來殺死應用程序。請記住,因爲實例化是掛起的,所以我們沒有Word應用程序來使用Quit(),但是一個winword.exe進程正在運行,我們需要終止它。 (我們如何殺死進程:https://gist.github.com/JuergenGutsch/92b64117cf51c15bab83

這解決了懸掛進程的問題,我們得到一個新問題,在3000次調用中會發生一次或兩次。新問題是一個安全問題,它會禁用所有Word加載項,也會禁用包含VBA宏的一些自定義dotm模板。

我們沒有收到任何異常,我們在事件日誌中沒有得到任何條目。除了這一個殺死進程之後立即:

An exception of type 'System.Runtime.InteropServices.COMException' occurred in BIS.MEDCS.Connectivity.Word.VSTO.dll but was not handled in user code 

Additional information: Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)). 

但是,這個異常處理與重試和實例化與下一個嘗試。

有沒有人知道這裏發生了什麼?

+0

這看起來很像當分配給對象的進程沒有完全釋放並且對象未被「清理」時出現的錯誤。可能重試發生得太快?也許你應該嘗試強制釋放COM對象以及垃圾回收? –

+0

非常感謝:)我們在等待15秒鐘後再次嘗試實例。也許這太快了。何我們發佈一個沒有實例的COM對象?我們重試,因爲實例化不起作用。 –

回答

0

您需要即刻發佈基礎COM對象。使用System.Runtime.InteropServices.Marshal.ReleaseComObject可以在完成使用後釋放Word對象。然後在Visual Basic中將變量設置爲Nothing(C#中的空值)以釋放對該對象的引用。請閱讀Systematically Releasing Objects文章中的更多內容。該文章與OUtlook相關,但相同的規則可應用於包括Word在內的所有Office應用程序。

將內存中的COM對象(不減少引用計數器)留在內存中可能會導致進程在主機關閉後保持運行。

+0

謝謝:)我只是嘗試了這一點。事實上,以前的單詞實例沒有這樣清理。 –

+0

這不幸並沒有改變任何東西。 Word應用程序的初始化仍然是隨機掛起的,並且會達到超時。超時後,我無法以這種方式進行清理,因爲我沒有COM實例。 –

1

除了@Eugene,垃圾收集不發生「立即」,但是,「最好的機會」,你可能會看到一個放緩清潔運行情況(特別是如果COM對象還沒有公佈正確)

要強制垃圾收集執行:

GC.Collect 
GC.WaitForPendingFinalizers 
GC.Collect 
GC.WaitForPendingFinalizers 

正如一個頭,重複的是不是一個錯誤,就這樣,你需要執行的是收集完成,由於.NET對象存儲在內存的方式和WaitForPendingFinalizers兩次。

所以首先確保你自己釋放你的物體並在最後的度假村收集垃圾。

+0

非常感謝:)正如我在其他評論中所說,以前的單詞實例並沒有真正清理這種方式,我只是試試 –