WinWord.exe 在调用 Word.Documents.Add 后不会退出 - Word .NET Interop
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2511464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WinWord.exe won't quit after calling Word.Documents.Add - Word .NET Interop
提问by Keith
I'm running into the classic scenario where, when creating Word COM objects in .NET (via the Microsoft.Office.Interop.Word assembly), the WinWord process won't exit even though I'm properly closing and releasing the objects.
我遇到了经典场景,在 .NET 中创建 Word COM 对象(通过 Microsoft.Office.Interop.Word 程序集)时,即使我正确关闭和释放对象,WinWord 进程也不会退出。
I've narrowed it down to the use of the Word.Documents.Add() method. I can work with Word in other ways without a problem (opening documents, modifying contents, etc) and WinWord.exe quits when I tell it to. It's once I use the Add() method (and only when adding a template) that the process is left running.
我已将范围缩小到 Word.Documents.Add() 方法的使用。我可以以其他方式使用 Word 没有问题(打开文档、修改内容等),并且 WinWord.exe 在我告诉它时退出。一旦我使用 Add() 方法(并且仅在添加模板时),进程就会保持运行。
Here is a simple example which reproduces the problem:
这是一个重现问题的简单示例:
Dim word As New Word.Application()
word.Visible = False
Dim documents As Word.Documents = word.Documents
Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath), NewTemplate:=False, DocumentType:=Word.WdNewDocumentType.wdNewBlankDocument, Visible:=False)
'' dispose objects
doc.Close()
While (Marshal.ReleaseComObject(doc) <> 0)
End While
doc = Nothing
While (Marshal.ReleaseComObject(documents) <> 0)
End While
documents = Nothing
word.Quit()
While (Marshal.ReleaseComObject(word) <> 0)
End While
word = Nothing
GC.Collect()
As you can see I'm creating and disposing the objects properly, even taking the extra step to loop Marsha.ReleaseComObject until it returns the proper code. Working with the Word objects is fine in other regards, it's just that pesky Documents.Add that is causing me grief. Is there another object that gets created in this process that I need to reference and dispose of? Is there another disposal step I need to follow? Something else? Your help is much appreciated :)
正如您所看到的,我正在正确地创建和处理对象,甚至采取额外的步骤来循环 Marsha.ReleaseComObject 直到它返回正确的代码。使用 Word 对象在其他方面很好,只是讨厌的 Documents.Add 使我感到悲伤。在这个过程中是否有另一个我需要引用和处理的对象?我还需要遵循其他处置步骤吗?还有什么?非常感谢您的帮助 :)
Update:I tried GC.Collect at the end of the disposal step but still no luck.
Update:我在处理步骤结束时尝试了 GC.Collect,但仍然没有运气。
Update 2:I've narrowed the problem down to the use of custom templates. When I invoke Documents.Add(...) I specify a custom template for the new document. If I don't do this and instead invoke Add() with no parameters, then the problem does not happen.
Update 2:我已将问题缩小到使用自定义模板。当我调用 Documents.Add(...) 时,我为新文档指定了一个自定义模板。如果我不这样做,而是调用不带参数的 Add(),那么问题就不会发生。
采纳答案by Keith
I figured out that the use of Documents.Add() when using a custom templateis to blame. I can't explain why this would leave WinWord.exe hanging. However there are other ways to create documents from templates that don't result in the same problem.
我发现在使用自定义模板时使用Documents.Add()是罪魁祸首。我无法解释为什么这会导致 WinWord.exe 挂起。但是,还有其他方法可以从不会导致相同问题的模板创建文档。
So I replaced:
所以我替换了:
Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath))
with:
和:
Dim doc As Word.Document = documents.Add()
doc.AttachedTemplate = templatePath
doc.UpdateStyles()
Using AttachedTemplate to specify the template works for me and doesn't leave WinWord.exe hanging.
使用 AttachedTemplate 指定模板对我有用,并且不会让 WinWord.exe 挂起。
(One new issue has arisen however... An image in the template's footer does not get copied to the document when using AttachedTemplate/UpdateStyles. I'm taking that up as a separate issue. But since this method solves my original problem, I'm satisfied. Thanks to everyone who offered answers!)
(然而,出现了一个新问题......使用 AttachedTemplate/UpdateStyles 时,模板页脚中的图像不会被复制到文档中。我将其视为一个单独的问题。但由于这种方法解决了我原来的问题,我很满意。感谢所有提供答案的人!)
回答by Dinah
(All of my advice is adapted from this answerabout Excel interop.)
(我所有的建议都改编自这个关于 Excel 互操作的答案。)
There are a few important things here:
这里有一些重要的事情:
1) Never use 2 dots on the same line. Also consider an indexer as a dot
1) 切勿在同一行上使用 2 个点。还可以将索引器视为一个点
Good
好的
Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(/*...*/);
BAD
坏的
Word.Document aDoc = wordApp.Documents.Open(/*...*/);
2) Release all of your pointers.
2)释放所有的指针。
3) No really, go back and release all of your pointers, you missed one somewhere (or at least I always do).
3) 真的没有,回去释放你所有的指针,你在某个地方错过了一个(或者至少我总是这样做)。
Here's a full example of what FINALLY worked for me on one project after much wailing and gnashing of teeth:
这是一个完整的例子,说明在我苦苦哀求和咬牙切齿之后,我终于在一个项目上成功了:
object m = Missing.Value;
// this must be an object, not a string. if you forget though,
// intellisense will remind you
object oFilename = @"C:\my sheet.doc";
object readOnly = false;
object isVisible = false;
Word.Application wordApp = new Word.ApplicationClass();
wordApp.Visible = false;
// remember: don't use 2 dots on 1 line
Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(ref oFilename, ref m, ref readOnly, ref m,
ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref isVisible,
ref m, ref m, ref m, ref m);
aDoc.Activate();
object findText = "my old value";
object replaceText = "new and improved value";
object oTrue = true;
object oFalse = false;
object replace = 2;
object wrap = 1;
Word.Selection s = wordApp.Selection;
Word.Find f = s.Find;
f.Execute(ref findText, ref oTrue,
ref oTrue, ref oFalse, ref oFalse,
ref oFalse, ref oTrue, ref wrap, ref oFalse,
ref replaceText, ref replace, ref oFalse, ref oFalse,
ref oFalse, ref oFalse);
aDoc.SaveAs(ref oFilename, ref m, ref m, ref m, ref m, ref m, ref m,
ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m);
object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
// casting here because intellisense complained of ambiguity
(aDoc as Word._Document).Close(ref doNotSaveChanges, ref m, ref m);
// release each in the reverse of the order in which it was first used
// ReleaseComObject might also work as well. I haven't tested yet
Marshal.FinalReleaseComObject(f);
Marshal.FinalReleaseComObject(s);
Marshal.FinalReleaseComObject(aDoc);
Marshal.FinalReleaseComObject(d);
// must quit app before releasing
// again: casting because intellisense complained of ambiguity
(wordApp as Word._Application).Quit(ref m, ref m, ref m);
Marshal.FinalReleaseComObject(wordApp);
回答by heringer
I got the same problema when i was doing it:
我在做的时候遇到了同样的问题:
object missing = System.Reflection.Missing.Value;
wordApplication.Quit(ref missing, ref missing, ref missing);
I solved this way:
我是这样解决的:
object objFalse = false;
wordApplication.Quit(ref objFalse, ref objFalse, ref objFalse);
Don't ask me why, automating office is an adventure :)
不要问我为什么,自动化办公是一种冒险:)
回答by Jim L
Have you tried changing
你有没有试过改变
oWord.Visible = False
to
到
oWord.Visible = True
?
?
I ask because Word may be asking you to do something that's related to this template you are trying to use. If it thinks there's a dialog showing, it will normally not shut down. IIRC, there's a way to do Quit so that it forces Quit and won't wait on any dialogs. But, it's been a while.
我问是因为 Word 可能会要求您做一些与您尝试使用的模板相关的事情。如果它认为有一个对话框显示,它通常不会关闭。IIRC,有一种方法可以执行退出,以便它强制退出并且不会等待任何对话框。但是,已经有一段时间了。
回答by Ahmad Mageed
Try calling GC.WaitForPendingFinalizers()and using Marshal.FinalReleaseComObjectinstead of Marshal.ReleaseComObject. This gets rid of the need to loop it.
尝试调用GC.WaitForPendingFinalizers()和使用Marshal.FinalReleaseComObject代替Marshal.ReleaseComObject. 这摆脱了循环它的需要。
Update your code to this and try it (the GC calls are in the beginning on purpose):
将您的代码更新为此并尝试它(GC 调用是故意在开始时):
GC.Collect()
GC.WaitForPendingFinalizers()
oDoc.Close()
Marshal.FinalReleaseComObject(oDoc)
Marshal.FinalReleaseComObject(oDocuments)
oWord.Quit()
Marshal.FinalReleaseComObject(oWord)
You might also want to check out this related questiondiscussing the issue for Excel.
您可能还想查看讨论 Excel 问题的相关问题。
回答by Ehz
I've only done Excel automation, but have run into similar problems. Referencing some old code, the final step in closing has the line GC.Collect()
我只做过 Excel 自动化,但遇到了类似的问题。引用一些旧代码,关闭的最后一步是 GC.Collect()
This article mentions it too: http://support.microsoft.com/kb/317109
这篇文章也提到了它:http: //support.microsoft.com/kb/317109
回答by Celebrating Octopus Emoji
I came across your post because of a similar issue with the template. I would get a message prompting me to save the .dotm file whenever I would try to close word in my program. I couldn't use your accepted answer because I don't have an exact template path, I just open whatever document the program receives.
由于模板的类似问题,我遇到了您的帖子。每当我尝试关闭程序中的 word 时,都会收到一条消息,提示我保存 .dotm 文件。我无法使用您接受的答案,因为我没有确切的模板路径,我只是打开程序收到的任何文档。
what I used is
我用的是
Word.NormalTemplate.Saved = true;
when I used that code before I disposed of the application, it would no longer bring up the dialog saying I hadn't saved the template, and it would run the disposal without leaving the unwanted "winWord.exe" process running.
当我在处理应用程序之前使用该代码时,它不会再弹出对话框说我没有保存模板,并且它会在不让不需要的“ winWord.exe”进程运行的情况下运行处理。
I got the "NormalTemplate.Saved" tip from the user "NeedSomeAnswers" on the visual basic forums here. In his words "[it] doesn't actually save to the Normal, it just tells Word that the Normal has already been saved so it doesn't need to save it".
我从这里的视觉基础论坛上的用户“ NeedSomeAnswers”那里得到了“NormalTemplate.Saved”提示。用他的话来说,“[它] 实际上并没有保存到法线,它只是告诉 Word 法线已经被保存,所以它不需要保存它”。
I think this is a second answer to the same problem. I hope it helps.
我认为这是同一问题的第二个答案。我希望它有帮助。
Have an awesome day, and be well.
祝你有美好的一天,好好的。
-any day your code works is a good day to celebrate-
-您的代码运行的任何一天都是值得庆祝的好日子-
回答by user5535483
I had tried to automate a document's creation in word from vb.net, but winword.exe was still running, even after I closed the document. I stumbled upon a solution to this problem; I moved the dim of the word object to inside the subroutine I was using to edit the document, as opposed to dimensioning it independent of a subroutine (my initial method).
我曾尝试从 vb.net 用 word 自动创建文档,但 winword.exe 仍在运行,即使在我关闭文档之后。我偶然发现了这个问题的解决方案;我将 word 对象的暗淡移动到我用来编辑文档的子例程内部,而不是独立于子例程(我的初始方法)对其进行尺寸标注。
Hope this helps.
希望这可以帮助。
回答by John Clegg
oWord.Visible = True
Solved the problem for me. The underlying issue was document recovery. A dialog was appearing despite having a line:
为我解决了问题。根本问题是文档恢复。尽管有一行,但出现了一个对话框:
_wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
I used every trick that has been shown here but until the document recovery list was cleared a "zombie" word process was left behind each time my application ran.
我使用了此处显示的所有技巧,但在清除文档恢复列表之前,每次我的应用程序运行时都会留下一个“僵尸”字处理程序。
回答by Abdul Kader Jilani
this is a perfect solution, i had same problem, i just followed this one and it is working perfect.
这是一个完美的解决方案,我遇到了同样的问题,我只是按照这个解决方案,它运行得很完美。
object objFalse = false;
对象 objFalse = 假;
wordApplication.Quit(ref objFalse, ref objFalse, ref objFalse);
wordApplication.Quit(ref objFalse, ref objFalse, ref objFalse);

