How to “free” an Microsoft.Office.Interop.Word.App

2019-08-12 19:30发布

问题:

What are alternatives to "free" this object? it normally happens when call the .Exit() method is called, but in this case, I can't do this because the user that should close the word application instance. I thought to do wordApp = null or call GC.Collect(); what's the best solution and why? thanks in advance.

I'm using this currently:

   public static void Free()
    {
        if (wordApp != null)
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
            GC.Collect();
        }
    }

回答1:

The most aggressive way to ensure that the Interop object is properly released is the using the double CollectWaitForPendingFinalizers pattern, adapted from Releasing COM Objects:

Marshal.ReleaseComObject(wordApp);
wordApp = null;
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

One area of interop between the managed world and the unmanaged world in which you need to be especially careful is in cleanly releasing COM objects when you're done with them. In the foregoing examples, we managed to achieve all the behavior we wanted using standard garbage collection. The only slight enhancement was to call GC.Collect twice to ensure that any memory that was available for collection but survived the first sweep was collected on the second sweep.



回答2:

A less agressive way to do it is like this

        // Make sure to exit app first
        object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
        object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat;
        object routeDocument = false;

        ((_Application)wordApp).Quit(ref saveOption, ref originalFormat, ref routeDocument);

        if (wordApp!= null)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);

        // Set to null
        wordApp= null;

Make sure however that all documents have been closed and or closed and saved!



回答3:

From MSDN

To address those situations when the value returned by ReleaseComObject is greater than zero, you can call the method in a loop that executes ReleaseComObject until the returned value is zero:

Dim wrd As New Microsoft.Office.Interop.Word.Application
Dim intRefCount As Integer
Do 
  intRefCount = System.Runtime.InteropServices.Marshal.ReleaseComObject(wrd)
Loop While intRefCount > 0
wrd = Nothing