2011-10-25 61 views
0

我有一個(舊版VB.Net)應用程序,從某些表中提取數據,填充一個單詞模板,並將該模板與其他幾個文件連接起來。延遲創建Microsoft.Office.Interop.Word.Application

在多臺機器上,這個工作沒有問題,但是對於一個客戶端,當Word Interop代碼嘗試打開模板文件(存在且沒有權限問題等)時拋出Object reference not set to an instance of an object存在一個持續性問題。

Dim doc As Document 
Dim msWord As Microsoft.Office.Interop.Word.Application 

msWord = New Microsoft.Office.Interop.Word.Application 
' next line throws "Object reference not set to an instance of an object" 
doc = msWord.Documents.Add(verifiedTemplateName) 

當拋出了一堆模態對話框的一個(可怕實現)調試模式下操作開始正停止執行時,不引發異常。

Dim doc As Document 
Dim msWord As Microsoft.Office.Interop.Word.Application 

msWord = New Microsoft.Office.Interop.Word.Application 
MsgBox("VooDoo coder at work") 
' now no exception is thrown 
doc = msWord.Documents.Add(verifiedTemplateName) 

當在正常模式下操作,延遲幾秒鐘時,不會拋出異常。

Dim doc As Document 
Dim msWord As Microsoft.Office.Interop.Word.Application 

msWord = New Microsoft.Office.Interop.Word.Application 
Delay(5) ' function that pauses for one second 
' now no exception is thrown 
doc = msWord.Documents.Add(verifiedTemplateName) 

這表明,在某些機器上,Word.Application需要一些時間來「旋轉起來」。

但是,如何最好地捕捉這個,並且一旦存在就繼續;或者如果時間框架是淫穢的(如同總是由當地司法管轄區決定的那樣),則拋出錯誤?

這也是別人在MSDN論壇報@WordApplication.Documents.Add Method return null?

的問題的唯一建議的解決方案我已經看到了潛在的無限循環:

Document nulldoc = null; 
do 
{ 
    document = application.Documents.Add(template, newtemplate, documenttype, visible); 
    Thread.Sleep(100); 
} 
while (document == nulldoc); 

是否有更好的解決方案這比愚蠢的延遲,或可能無限的檢查循環?

另請參見:Error when creating an instance of Word in VB.net.同錯誤,類似的代碼;但解決方案是確保目標文件存在(在我的情況下)。

回答

1

記得解決問題與忙碌了進程內COM服務器(Visual Studio中在我的情況)進行通信,通過實施the COM IMessageFilter interface(這是一樣System.Windows.Forms.IMessageFilter)。

this MSDN article有一個技術的例子。

由於您的問題發生在Word中忙啓動,它可以是,這種技術將幫助。

順便說一句,如果您正在做自動化Office,您很可能會遇到Office無法退出的問題,as described in this KB article

爲了解決這個問題,你需要小心地對你實例化的每個COM對象調用Marshal.ReleaseComObject,最好是在try/finally構造中。爲了確保不會錯過任何引用,請避免使用「雙點」構造msWord.Documents.Add,而是顯式創建對msWord.Documents的引用。

你的代碼應該看起來更像(我猜VB。NET語法,但你會明白):

Dim msWord As Application 
Dim doc As Document 
Dim docs As Documents 

Try 
    msWord = ... 
    docs = msWord.Documents 
    ' Test if docs is Nothing to avoid a NullReferenceException 
    If Not docs Is Nothing Then 
     doc = docs.Add... 
     ... 
    End If 
    ... 
Finally 
    If Not doc Is Nothing Then Marshal.ReleaseComObject doc 
    If Not docs Is Nothing Then Marshal.ReleaseComObject docs 
    If Not msWord Is Nothing Then 
     msWord.Quit 
     Marshal.ReleaseComObject msWord 
    End If 
End Try 
+0

謝謝。我實際上使用Marshal.FinalReleaseComObject()作爲詳細的@ https://blogs.msdn.com/b/yvesdolc/archive/2004/04/17/115379.aspx –