Destroy those pesky orphaned Excel processes in .Net programs

If you have ever worked with Excel in the .Net environment, you likely have run across the occasional orphan and they can be a pain to clean up

Recently I was doing just this, and my Task Manager was filling up with orphans fast.  I was calling for the Excel Process to close, but that wasn't working most of the time.  So I came up with a more elaborate way to make them disappear.  Basically I found out that in order to close the application, you have to close the workbooks, and in order to close the workbooks, you have to close each workbook individually, and to close those, you have to close each worksheet in those workbooks individually.  I also included COM management, so we are hitting this with multiple attacks to make sure they stay dead!  So the super-overkill-do-everything process is:

 

  1. Collect each worksheet individually
  2. Collect each workbook individually
  3. Delete the worksheets
  4. Release the worksheets
  5. Null the worksheets
  6. Delete the workbooks
  7. Release the workbooks
  8. Null the workbooks
  9. Close the workbooks collection
  10. Quit the application
  11. Release the application
  12. Null the application
  13. Collect garbage

 

Here's how

After your work is done, you are left with a Microsoft.Office.Interop.Excel.Application named 'exc', call killExcel(exc):

protected void killExcel(Microsoft.Office.Interop.Excel.Application exc)
{
    try
    {
        List<Microsoft.Office.Interop.Excel.Workbook> wbs = new List<Microsoft.Office.Interop.Excel.Workbook>();
        List<Microsoft.Office.Interop.Excel.Worksheet> wss = new List<Microsoft.Office.Interop.Excel.Worksheet>();
        foreach (Microsoft.Office.Interop.Excel.Workbook wb in exc.Workbooks)
        {
            foreach (Microsoft.Office.Interop.Excel.Worksheet ws in wb.Worksheets)
                wss.Add(ws); // collect worksheets
            wbs.Add(wb); // collect workbooks
        }
        for (int i = 0; i < wss.Count; i++)
        {
            wss[i].Delete();
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wss[i]); // release it
            wss[i] = null; // null it
        }
        for (int i = 0; i < wbs.Count; i++)
        {
            wbs[i].Close(null, null, null);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs[i]); // release it
            wbs[i] = null; // null it
        }
        exc.Workbooks.Close(); // so you can close this
        exc.Quit(); // so you can quit this
        System.Runtime.InteropServices.Marshal.ReleaseComObject(exc); // release it
        exc = null;
        GC.Collect(); // this sets up the finalizers
        GC.WaitForPendingFinalizers();
        GC.Collect(); //apparently this kills it
        GC.WaitForPendingFinalizers();
    }
    catch (Exception ex)
    {
        // deal with it fool!
    }
}

Yes this is overkill, but I think I covered all possible ways to kill you processes, so they should be more dead than Elvis; no more orphans - yay for iteration!

 

Some useful links:

http://www.thescarms.com/dotnet/ExcelObject.aspx 

http://www.devcity.net/Articles/239/3/article.aspx 

http://krgreenlee.blogspot.com/...ting-excel_10.html 

Comments (3) -

  • It is very useful. Thank you.
  • Thanks a lot, very nice bit of code! Love complete, well presented and watertight solutions. Good work!
  • Thanks for this, great coding! At last, a remedy for the massive headache these orphan processes have caused me today!

Add comment

Loading