Why does Microsoft.Office.Interop.Excel.Application.Quit() leave the background process running?

22,996

Solution 1

Got it!

application.Workbooks != application.Workbooks

This property doesn't expose a variable, it generates a value. So every time I access the Workbooks property I create a new COM object.

I fixed the code and all is well. Thanks, everybody.

var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = workbooks.Open(pathToExcelWorkbook); // Fixed

workbook.Close();
workbooks.Close();
excelApplication.Quit();

Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);

Solution 2

This is a widely-spread issue with Office applications. All Excel add-ins/automation applications should systematically release their references to Excel objects when they are no longer needed. Failing to systematically release reference to Excel objects can prevent Microsoft Office Excel from shutting down properly. See Systematically Releasing Objects for more information. It is related to Outlook, but the same principles can be applied to all Office applications.

Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Excel object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object.

Solution 3

THIS IS WRONG WAY TO DO LIKE THIS, but this is most easy way to fix the issue:

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    private Application _excelApp;
    private Workbook _excelWorkBook;
    private Worksheet _excelSheet;

    private void CloseExcelApp()
    {
        int hWnd = _excelApp.Application.Hwnd;
        uint processID;

        GetWindowThreadProcessId((IntPtr)hWnd, out processID);
        Process.GetProcessById((int)processID).Kill();

        _excelWorkBook = null;
        _excelApp = null;
        _excelSheet = null;
    }

all you need is to init all uninitialized variables when you need to work with it, and call CloseExcelApp() when you need to close app.

Share:
22,996
skinnysoftware
Author by

skinnysoftware

Updated on July 05, 2022

Comments

  • skinnysoftware
    skinnysoftware almost 2 years

    The following code leaves a Microsoft Excel background process running, until after my program has exited:

    var excelApplication = new Application();
    var workbooks = excelApplication.Workbooks;
    var workbook = excelApplication.Workbooks.Open(file.FullName);
    
    workbook.Close();
    excelApplication.Workbooks.Close();
    excelApplication.Quit();
    
    Marshal.ReleaseComObject(workbook);
    Marshal.ReleaseComObject(workbooks);
    Marshal.ReleaseComObject(excelApplication);
    

    Why? What am I missing?

  • keeehlan
    keeehlan over 9 years
    Seems like a reasonable response, not sure why you were downvoted
  • Mitja Bezenšek
    Mitja Bezenšek over 9 years
    Is this still the case in the newer Office versions? The link you posted links to the 2007 information. And if I change the version of the documentation ("Other versions" dropdown) there is no info about System.Runtime.InteropServices.Marshal.ReleaseComObject for 2010 or 2013.
  • skinnysoftware
    skinnysoftware about 8 years
    Hi @eugene - Your answer certainly led me in the right direction, but I didn't find it to be specific enough to solve the entire problem. If you compare line 3 in my two code samples you will see that the problem was my failure to understand that the Workbooks property will always return a new object.
  • Eugene Astafiev
    Eugene Astafiev about 8 years
    The same can be applied to newer Office versions.
  • Jerome
    Jerome about 6 years
    Right! And if man use worksheet, man shall release this object too!
  • Fandango68
    Fandango68 over 5 years
    This still leaves the object in the task list. Setting it to NULL did not help (in C#)
  • Fandango68
    Fandango68 over 5 years
    What did you do differently? The answer above is no different
  • skinnysoftware
    skinnysoftware over 5 years
    @Fandango68 - The fix is on line 3, as commented.