N/Direct - The .NET Interoperability Resource Center 

FAQ

 

 

 

Most Valuable Professional

When I automate an Office application, it remains in memory even after I call Quit(). Why?
Written: 7/1/2002 Updated: 3/25/2003

If the Office application (Word, Excel etc.) remains in memory, even though you call Quit(), you can almost be certain that the problem is that all COM references haven't been released properly. The .NET runtime will call Release when the RCW object is garbage collected, which can happen some time after the object goes out of scope or is no longer referenced from managed code. To release the COM object in a timely manner, you should use the ReleaseComObject() method of the Marshal class.

Note that "hidden" objects might be created while walking the automation object model, for example collection classes that you never keep a reference to, only retrieve temporarily from a property. You have to carefully think about where objects are created, and properly release them. In the following example, Excel will likely stick around for a while, because the Workbooks collection object is not explicitly released.

C#
static void UseExcel()
{
  Excel.Application app = new Excel.Application();
  Console.WriteLine( app.Workbooks.Count );
  app.Quit();
  Marshal.ReleaseComObject( app );
}
    

VB.NET
Shared Sub UseExcel()
  Dim app As New Excel.Application
  Console.WriteLine(app.Workbooks.Count)
  app.Quit()
  Marshal.ReleaseComObject(app)
End Sub
    

To correct the problem, keep a reference to the collection and release it when you're done.

C#
static void UseExcel()
{
  Excel.Application app = new Excel.Application();
  Excel.Workbooks wbs = app.Workbooks;
  Console.WriteLine( wbs.Count );
  app.Quit();
  Marshal.ReleaseComObject( wbs );
  Marshal.ReleaseComObject( app );
}
    

VB.NET
Shared Sub UseExcel()
  Dim app As New Excel.Application
  Dim wbs As Excel.Workbooks = app.Workbooks
  Console.WriteLine(wbs.Count)
  app.Quit()
  Marshal.ReleaseComObject(wbs)
  Marshal.ReleaseComObject(app)
End Sub
    

All this cleanup work can get pretty ugly if you use a lot of objects, and eventually make the code harder to read. Another possible solution is to skip the explicit releases, and then force a garbage collection to happen when you're done. To force a collection, use the GC class' methods Collect() and WaitForPendingFinalizers(). Don't overuse this technique out of laziness, it can hurt performance if used too often.

C#
static void UseExcel()
{
  Excel.Application app = new Excel.Application();
  Console.WriteLine( app.Workbooks.Count );
  app.Quit();
  app = null;
  GC.Collect();
  GC.WaitForPendingFinalizers();
}
    

VB.NET
Shared Sub UseExcel()
  Dim app As New Excel.Application
  Console.WriteLine(app.Workbooks.Count)
  app.Quit()
  app = Nothing
  GC.Collect()
  GC.WaitForPendingFinalizers()
End Sub
    

See also
PRB: Office Application Does Not Quit After Automation from Visual Studio .NET Client (317109)