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 t
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 :)
I figured out that the use of Documents.Add() when using a custom template is 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.
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.
(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!)
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()
This article mentions it too: http://support.microsoft.com/kb/317109
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.
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).
Hope this helps.
(All of my advice is adapted from this answer about Excel interop.)
There are a few important things here:
1) Never use 2 dots on the same line. Also consider an indexer as a dot
Good
Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(/*...*/);
BAD
Word.Document aDoc = wordApp.Documents.Open(/*...*/);
2) Release all of your pointers.
3) No really, go back and release all of your pointers, you missed one somewhere (or at least I always do).
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);