snippetcsharpCritical
How do I properly clean up Excel interop objects?
Viewed 0 times
properlyhowobjectsinteropexcelclean
Problem
I'm using the Excel interop in C# (
Although this kind of works, the
What am I doing wrong, or is there an alternative to ensure interop objects are properly disposed of?
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:
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:
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
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
Code Snippets
Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);Worksheets sheets = excelApp.Worksheets; // <-- The important part
Worksheet sheet = sheets.Open(...);
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);Context
Stack Overflow Q#158706, score: 715
Revisions (0)
No revisions yet.