我有一个使用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属性吗?
答案 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's的code位使用的代码,而 应该为您提供您所追求的内容:
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);
}