Search code examples
c#excelinteropcom-interop

How do I properly clean up Excel interop objects?


I'm using the Excel interop in C# (ApplicationClass) and have placed the following code in my finally clause:

while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { }
excelSheet = null;
GC.Collect();
GC.WaitForPendingFinalizers();

Although this kind of works, the Excel.exe process is still in the background even after I close Excel. It is only released once my application is manually closed.

What am I doing wrong, or is there an alternative to ensure interop objects are properly disposed of?


Solution

  • Excel does not quit because your application is still holding references to COM objects.

    I guess you're invoking at least one member of a COM object without assigning it to a variable.

    For me it was the excelApp.Worksheets object which I directly used without assigning it to a variable:

    Worksheet sheet = excelApp.Worksheets.Open(...);
    ...
    Marshal.ReleaseComObject(sheet);
    

    I didn't know that internally C# created a wrapper for the Worksheets COM object which didn't get released by my code (because I wasn't aware of it) and was the cause why Excel was not unloaded.

    I found the solution to my problem on this page, which also has a nice rule for the usage of COM objects in C#:

    Never use two dots with COM objects.


    So with this knowledge the right way of doing the above is:

    Worksheets sheets = excelApp.Worksheets; // <-- The important part
    Worksheet sheet = sheets.Open(...);
    ...
    Marshal.ReleaseComObject(sheets);
    Marshal.ReleaseComObject(sheet);
    

    POST MORTEM UPDATE:

    I want every reader to read this answer by Hans Passant very carefully as it explains the trap I and lots of other developers stumbled into. When I wrote this answer years ago I didn't know about the effect the debugger has to the garbage collector and drew the wrong conclusions. I keep my answer unaltered for the sake of history but please read this link and don't go the way of "the two dots": Understanding garbage collection in .NET and Clean up Excel Interop Objects with IDisposable