0

How can I guarantee the MS Word process exits (using C# Interop library)?

My current approach:

// close word document ("doc")
((_Document)doc).Close(SaveChanges: WdSaveOptions.wdDoNotSaveChanges);
if (doc != null)
{
    System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
    doc = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

// close word application ("word")
((_Application)word).Quit(false);
if (word != null)
{
    System.Runtime.InteropServices.Marshal.ReleaseComObject(word);
    word = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

// and here is how it fails
Process[] pname = Process.GetProcessesByName("WINWORD");
Assert.IsTrue(pname.Length == 0);

Sources:

c# MSOffice Interop Word will not kill winword.exe

Disposing of Microsoft.Office.Interop.Word.Application

Microsoft.Interop object won't quit or "release"

Excel interop COM doesn't close

Ambiguity in Word Interop code

Community
  • 1
  • 1
ecoe
  • 4,994
  • 7
  • 54
  • 72
  • 2
    Double check that you aren't breaking the two-dot rule, and that you're disposing every office object you create like the ones in your example. I also wouldn't be surprised if you're still seeing the process simply because you check for it immediately after your cleanup code. – helrich Feb 26 '15 at 19:59
  • yup, it was all timing - I now realize you gotta wait a bit. Thanks – ecoe Feb 26 '15 at 20:36

2 Answers2

1

There is no need to use ReleaseComObject if you use the GC methods for swiping the heap. Also be aware, you need to call the GC methods twice:

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

Anyway, I always recommend using System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Office (Word) object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. You can read more about that in the Systematically Releasing Objects article. It is related to Outlook, but the same rules can be applied to any Office aplication (including Word).

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
1

It's work for me in any case

Word.Application app = null;
Word.Document doc = null;
Word.Tables tables = null;
Word.ContentControls mainControls = null;

try
{
    app = new Word.Application();
    app.ScreenUpdating = false;
    app.Visible = false;
    app.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
    doc = app.Documents.Open(fileName);
    tables = doc.Tables;
        //.. my code 
        if (tables.Count < 1)
        val = mainControls[2].Range.Text ?? "";
        //end of my code
    }
catch (Exception exc) { G.log(exc); }
finally
{
    //CLEAN UP
    GC.Collect();
    GC.WaitForPendingFinalizers(); 
    if (mainControls != null)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(mainControls);
    if (tables != null)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tables);
    if (doc != null)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
    app.Quit();
    if (app != null)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
}