0

I am running my C# application which opens many excel files using loops but then in the end of each loop I call the below function to end the excel process but still the process in task manager is not ended and I am not sure why. Can anyone advise?

private void xlCleanup(Excel.Application xlApp, Excel.Workbook xlWorkbook, Excel.Worksheet xlWorksheet, Excel.Range xlRange)
    {
        //cleanup
        GC.Collect();
        GC.WaitForPendingFinalizers();

        //rule of thumb for releasing com objects:
        //  never use two dots, all COM objects must be referenced and released individually
        //  ex: [somthing].[something].[something] is bad

        //release com objects to fully kill excel process from running in the background
        if (xlRange != null || xlWorksheet != null)
        {
            Marshal.ReleaseComObject(xlRange);
            Marshal.ReleaseComObject(xlWorksheet);
        }
        //close and release
        
        xlWorkbook.Close(0);
        Marshal.ReleaseComObject(xlWorkbook);

        //quit and release
        xlApp.Quit();
        Marshal.ReleaseComObject(xlApp);

    }
Tak
  • 3,536
  • 11
  • 51
  • 93
  • The real reason you're having to manually release COM objects is because the thread you're using them on is not COM compliant. If it has a COM compliant, and has a COM compliant message pump then office COM instances will clean themselves up and ReleaseComObject is not necessary. – MikeJ Nov 18 '20 at 16:43
  • Here's some more info on why you should not use ReleaseCOMObject - https://devblogs.microsoft.com/visualstudio/marshal-releasecomobject-considered-dangerous/ and one that talks about the message pumping requirements - https://learn.microsoft.com/en-us/archive/blogs/cbrumme/apartments-and-pumping-in-the-clr – MikeJ Nov 18 '20 at 20:05
  • I should also point out that the articles are all old now, but that's because so is COM. – MikeJ Nov 18 '20 at 20:08

1 Answers1

0

Try adding this to the end of the method. It has resolved this problem for me:

xlRange = null;
xlWorksheet = null;
xlWorkbook = null;
xlApp = null;
GC.Collect();

(edited to set xl vars to null)

(edit #2)

Also read the answer here: How do I properly clean up Excel interop objects?

JesseChunn
  • 555
  • 3
  • 7
  • You don't need to set C# objects to null for them to be collected by the GC. – MikeJ Nov 18 '20 at 16:47
  • I understand, but for whatever reason, this is what I had to do to ensure the application fully released Excel. I don't claim to know why, I just claim it works (for me). Not setting them to null would sometimes allow Excel to remain "alive" in task manager. – JesseChunn Nov 18 '20 at 17:00
  • see my comment on the question. Also keep in mind that a debug build behaves differently than a release build as the debugger will keep alive locals. – MikeJ Nov 18 '20 at 19:55