如何正确关闭/终止WINWORD.EXE / Word互操作?

时间:2017-04-17 00:45:27

标签: .net vb.net ms-word interop office-interop

我有一个使用Word文件模板生成报告的应用程序。应用程序将使用用户的数据库记录提供的详细信息填充模板。我正在使用远程桌面将我的应用程序运行到另一台服务器。

我的问题是WINWORD.EXE进程无法终止并在报告生成完成后保留在任务管理器中(将报告保存到数据库并删除生成的文件)。

当服务帐户登录时,WINWORD.EXE进程正在正常终止,并且正在任务管理器列表中删除。注销时,WINWORD.EXE仍保留在列表中。当多个Word进程未终止时,这可能会导致内存不足。

Word报告是使用Microsoft.Office.Interop.Word生成的,版本= 12.0.0.0。

以下是保存新文件,关闭Word应用程序,保存报告以及删除生成的文件的代码:

Marshal.releaseComObject(rng)

Dim strFileName As String = comm.GenerateFileName(strUser_id, strVPN) & ".docx"

' Save the document.
Dim filename As Object = Path.GetFullPath(strNewFilePath & strFileName)
newDoc.SaveAs(FileName:=filename)

' Close.
Dim save_changes As Object = False
newDoc.Close(save_changes)
WordApp.Quit(save_changes)

Marshal.ReleaseComObject(newDoc)
Marshal.ReleaseComObject(WordApp)

rng= Nothing
newDoc = Nothing
WordApp = Nothing

' Let GC know about it
GC.Collect()

' Save the file to database
SaveFormat(Filename, strUser_Id, strFamilyId, strVPN, DateTime.Now.ToString(), "application/vnd.ms-word", br_id, "doc")

If File.Exists(filename) then
      File.Delete(filename)
End If

我还在研究这里的不同工作。

在Excel中,我们通过使用HWND属性和GetProcessById类获取打开的Excel实例的进程ID来获得解决方案。

我在某处读过Word 2013及更高版本的Application.HWND属性。 这是真的吗? Word有HWND属性吗?

4 个答案:

答案 0 :(得分:1)

使用垃圾收集器(GC)的清理代码如下所示:

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

当所有引用都被正确清除时,通常Word会清理(有一些延迟),但是如果你想强制清理(仍然确保清除所有引用之后)将使用上面的代码。

看起来有点奇怪,但是如果你想知道这些内容,请在第二章中找到安德鲁·怀特查佩尔(前办公室主任)https://www.amazon.com/Microsoft%C2%AE-Development-Microsoft-Developer-Reference/dp/0735621322的书,从头到尾。

答案 1 :(得分:1)

这段代码是我一直根据Siddharth Rout'scode位使用的代码,而 应该为您提供您所追求的内容:

Private Sub ReleaseObject(ByVal obj As Object)
    Try
        Dim intRel As Integer = 0
        Do
            intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
        Loop While intRel > 0
        obj = Nothing
    Catch ex As Exception
        obj = Nothing
    Finally
        GC.Collect()
    End Try
End Sub

将上述方法添加到您的应用程序中。然后,您可以在关闭Word时调用此方法。

值得注意的是,正确的订购非常重要。这似乎是Interop的一个问题。

我要做的是,替换这段代码:

newDoc.Close(save_changes)
WordApp.Quit(save_changes)

Marshal.ReleaseComObject(newDoc)
Marshal.ReleaseComObject(WordApp)

rng= Nothing
newDoc = Nothing
WordApp = Nothing

使用:

newDoc.Close(False)
ReleaseObject(newDoc)
WordApp.Quit(False)
ReleaseObject(WordApp)

我还可以看到您正在尝试处理您的rng变量。我会更改:Marshal.releaseComObject(rng)并使用新方法ReleaseObject(rng)

总的来说,您的代码看起来像是:

Dim strFileName As String = comm.GenerateFileName(strUser_id, strVPN) & ".docx"

' Save the document.
Dim filename As Object = Path.GetFullPath(strNewFilePath & strFileName)
newDoc.SaveAs(FileName:=filename)

ReleaseObject(rng)
newDoc.Close(False)
ReleaseObject(newDoc)
WordApp.Quit(False)
ReleaseObject(WordApp)

' Save the file to database
SaveFormat(Filename, strUser_Id, strFamilyId, strVPN, DateTime.Now.ToString(), "application/vnd.ms-word", br_id, "doc")

If File.Exists(filename) then
      File.Delete(filename)
End If

您提到使用GetProcessById方法然后终止Excel进程。这真的不是必须的,你可以使用上面的方法ReleaseObject。正如我所说,经常是导致问题的顺序。

特别关注我的answer

Dim app As New Excel.Application()
app.Visible = False
app.DisplayAlerts = False

Dim wbs As Excel.Workbooks = app.Workbooks
Dim wb As Excel.Workbook = wbs.Add()
Dim ws As Excel.Worksheet = CType(wb.Sheets(1), Excel.Worksheet)

ReleaseObject(ws)
wb.Close()
ReleaseObject(wb)
ReleaseObject(wbs)
app.Quit()
ReleaseObject(app)

答案 2 :(得分:0)

当我必须编写Word文档时,我总是打开文档,在Try[...]Catch中使用它然后关闭它:

Private Sub doSomethingWithWord()
    Dim oWord As Word.Application

    'Create document
    Dim oDoc As Word.Document
    oWord = CreateObject("word.Application")
    oDoc = oWord.Documents.Add

    Try
        'Do something
        Dim oPara1 As Word.Paragraph
        oPara1 = oDoc.Content.Paragraphs.Add
        oPara1.Range.Text = "Hello world"
        oPara1.Range.Font.Bold = True
        oPara1.Format.SpaceAfter = 24
        oPara1.Range.InsertParagraphAfter()

        'Everything is OK, then save!
        oDoc.Save()
    Catch ex As Exception
        MsgBox("Error")
    End Try

    'Whatever happens always finishes closing word
    oDoc.Close()
    oWord.Quit()

End Sub

答案 3 :(得分:0)

我找到了非常简单的解决方案。 Application对象具有Quit()方法,该方法可以正确关闭MS Word应用并释放所有关联的资源(并退出WINWORD.EXE进程)。

Application wordApp = new Application();
wordApp.Visible = false; // Show / hide MS Word app window
wordApp.ScreenUpdating = false; // Enable / disable screen updates after each change

try
{
    Document document = wordApp.Documents.Open("example.docx");

    // TODO: process the document here ...

}
finally
{
    wordApp.Quit(false);
}