Reputation: 11
We use Excel interop in numerous places in our code, however I have one function which doesn't ever seem to close down the Excel process it uses.. I've simplified the code down, and it just seems like whenever I open a workbook in this function it stays hanging around. I've included the code below, I've made sure every object is defined, released and nulled, and yet Excel stays running.
System.Data.DataTable dtExcelSheet = new System.Data.DataTable();
Microsoft.Office.Interop.Excel.Application excelObject = new Microsoft.Office.Interop.Excel.Application();
dtExcelSheet.Columns.Add("SheetName", typeof(string));
dtExcelSheet.Columns["SheetName"].ReadOnly = false;
dtExcelSheet.Columns["SheetName"].Caption = "Sheet Name";
Workbooks wbs = excelObject.Workbooks;
Workbook excelWorkbook = wbs.Add(excelFile);
excelWorkbook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
wbs.Close();
excelObject.Quit();
int i1 = Marshal.FinalReleaseComObject(excelWorkbook);
int i2 = Marshal.FinalReleaseComObject(wbs);
int i3 = Marshal.FinalReleaseComObject(excelObject);
excelWorkbook = null;
wbs = null;
excelObject = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
Upvotes: 1
Views: 5924
Reputation:
Same thing happened to me the other day. See my question on Excel Automation as to the fix (question deals with multiple row deletion mostly but I also had the same problem as you turns out it has to do with releasing all the COM objects properly).
Upvotes: 0
Reputation: 154
I tried running your code, but I could not reproduce the issue. If I step through it with a debugger, the Excel process terminates after the last call to FinalReleaseComObject
. Is it possible that the culprit lies in some code not present in your listing?
When using COM interop, I have found that it is all too easy to increment the reference count on COM objects in very subtle ways. For example, let's say you do something like this:
excelWorkbook.Foo.Bar();
This can increment the reference count on the Foo
object, leaving you with no means of releasing it afterwards...and leaving the Excel process lingering around until you shut down your app. You can re-write the above line of code like this:
Foo foo = excelWorkbook.Foo;
foo.Bar();
Marshal.ReleaseComObject(foo);
It's not as pretty, but it will decrement the reference count on the Foo
object after you are done using it.
Upvotes: 1
Reputation: 2327
It's been a while since I've mucked around with this stuff, so nothing jumps out at me.
My usual recommendation in these cases is to set your excel application object to Visible = true
to see if there's not a dialog popping up on you. Excel/Word will sometimes refuse to shut down if they think there's a modal dialog open no matter what else you may do. It's the first thing to check anyway.
Upvotes: 1
Reputation: 54999
Complete guess, but does this row:
dtExcelSheet.Columns.Add("SheetName", typeof(string));
return the column that is created?
If so you'd probably need to store that reference and clean that up at the end.
Edit: Also, I don't think you should be setting the variables to null at the end, I think that just accesses them again.
And you shouldn't have to tell the GC to collect etc, but I assume that might be your test code.
Upvotes: 1
Reputation: 33270
Make sure you're not calling Excel on a background thread. I had a similar problem where I was cleaning up all the COM objects, but Excel still wasn't dying and that turned out to be the problem.
I wrote up my experiences and a solution here.
Upvotes: 1