1

I have a C# program that opens an Excel file, reads a cell, closes the file, and exits Excel. Unfortunately, the Windows Task Manager still shows an Excel.exe process running. I've read just about every article concerning this issue and tried almost all of the solutions . . . and still have the same problem. I believe one of COM objects is not being released and thus hanging the process. However, I also believe that I've been very careful about instantiating the Excel objects (no double ".") and releasing them.

If I remove the "a = xlCells[1,1].Value" line, every thing releases and Excel dies cleanly after the FinalReleaseComObject of the Application instance. Why would this assignment create COM objects or interfere with them?

        Excel.Application xlApp = null;
        Excel.Workbooks xlWorkbooks = null;
        Excel.Workbook xlWorkbook = null;
        Excel.Sheets xlSheets = null;
        Excel.Worksheet xlWorksheet = null;
        Excel.Range xlCells = null;

        string inputFile = @"C:\Temp\test.xlsx";
        string a;

        xlApp = new Excel.Application();
        xlApp.Visible = false;
        xlApp.DisplayAlerts = false;
        xlWorkbooks = xlApp.Workbooks;
        xlWorkbook = xlWorkbooks.Open(inputFile);
        xlSheets = xlWorkbook.Sheets;
        xlWorksheet = xlSheets[1];
        xlCells = xlWorksheet.Cells;

        a = xlCells[1,1].Value;

        Marshal.FinalReleaseComObject(xlCells);
        xlCells = null;

        Marshal.FinalReleaseComObject(xlWorksheet);
        xlWorksheet = null;
        Marshal.FinalReleaseComObject(xlSheets);
        xlSheets = null;      
        xlWorkbook.Close(false, Type.Missing, Type.Missing);
        Marshal.FinalReleaseComObject(xlWorkbook);
        xlWorkbook = null;
        xlWorkbooks.Close();
        Marshal.FinalReleaseComObject(xlWorkbooks);
        xlWorkbooks = null;

        xlApp.Quit();
        Marshal.FinalReleaseComObject(xlApp);
        xlApp = null;
Mike Brown
  • 11
  • 1
  • 3
    xlCells[1,1] actually creates a Range excel object so if you want to keep the style of what you have been doing so far assign xlCells[1,1] to a Range and then try to dispose it like you have been doing. – Daneau Jul 23 '15 at 02:57
  • Are you really sure that you need to use the interop libraries for this? This is the kind of thing that would work much better using a managed library such as EPPlus or NPOI. – mason Jul 24 '15 at 13:46

2 Answers2

0

I would make two changes. First, since a Sheets item can be either a worksheet or a graph sheet, it's best to cast with As and check for null. Second, if you just want to get a range with an alphanumeric address, the get_Range() method works well. Otherwise, if you want to go by row and column indexes, then follow @Daneau's comment.

xlWorksheet = xlSheets[1] as Excel.Worksheet;
if(xlWorksheet != null)
{
    xlCells = xlWorksheet.get_Range("A1");
    a = xlCells[1,1].Value;

    Marshal.FinalReleaseComObject(xlCells);
    xlCells = null;

    Marshal.FinalReleaseComObject(xlWorksheet);
    xlWorksheet = null;
}
CtrlDot
  • 3,102
  • 3
  • 25
  • 32
  • You should never need to call ReleaseComObject. It is a VERY popular misconception. Please take the time to read through the accepted answer in [this question](http://stackoverflow.com/questions/25134024/clean-up-excel-interop-objects-with-idisposable). The reason Excel is hanging is the OP us using a debugger and either have not exited the method or hit the stop button instead of cleanly shutting down the program. – Scott Chamberlain Jul 24 '15 at 13:48
  • Thanks. I develop COM add-ins, which means my code never closes Excel and cannot release everything in one fell swoop with `GC.Collect()` and `GC.WaitForPendingFinalizers()`, but that link gives me some useful ideas. – CtrlDot Jul 24 '15 at 19:39
0

I changed up the code and added the dummy Range object.

Range tmpCell = xlCell[1,1];
a = tmpCell.Value;
Marshal.ReleaseComObject(tmpCell);

My problems went away. Much thanks, Daneau!

The real routine has several loops with the cell being evaluated. I thought it would work fine using the tmpCell for each new cell assignment, then release tmpCell at the end. That failed. Prior to each new tmpCell assignment to a xlCell[x,y], I had to release tmpCell. This worked, but is certainly cumbersome. It's difficult to believe that there's not a better way to manage this or keep track of the various COM objects.

Mike Brown
  • 11
  • 1
  • You should never need to call ReleaseComObject. It is a VERY popular misconception. Please take the time to read through the accepted answer in [this question](http://stackoverflow.com/questions/25134024/clean-up-excel-interop-objects-with-idisposable). The reason Excel is hanging is you are using a debugger and either have not exited the method or you hit the stop button instead of cleanly shutting down the program. – Scott Chamberlain Jul 24 '15 at 13:47