OneWileyDog
OneWileyDog

Reputation: 37

Cannot close Excel.exe after killing it from Task Manager

I am using Visual Studio 2015 Community in C#, and Office 2013 standalone.

The below code worked to open and close Excel. Then I added code to open a specific Worksheet as in Example 2 below. And, that worked, Excel closed correctly.

Then I moved things around but forgot to use the ReleaseComObject for the Worksheet and Excel stayed open, so I manually closed it in Task Manager.

Now, NONE of the below examples work. After I accidentally forgot to release the COM object, Excel never closes, unless I reboot my machine.

Example 1

private bool loadExcel()
{
    // Open Excel
    Excel.Application myApp = new Excel.Application();
    // Hide Excel
    myApp.Visible = false;
    GSIWorkbook = myApp.Workbooks.Open( "D:\\Test.xlsx" );
    // Cleanup
    GSIWorkbook.Close( false );
    // Manual disposal because of COM
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorkbook ) != 0 )
    { }

    myApp.Application.Quit();
    myApp.Quit();
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( myApp ) != 0 )
    { }

    myApp = null;
    GSIWorkbook = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();
    return true;

} // End loadExcel

Example 2

private bool loadExcel()
{
    // Open Excel
    Excel.Application myApp = new Excel.Application();
    // Hide Excel
    myApp.Visible = false;
    GSIWorkbook = myApp.Workbooks.Open( "D:\\Test.xlsx" );

    for ( int counter = 1; counter < 100; counter++ )
    {
        try
        {
            GSIWorksheet = GSIWorkbook.Sheets[counter];
            if ( GSIWorksheet.Name == _gsi2Sheet )
                break;
        }
        catch
        {
            continue;
        }
    }

    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorksheet ) != 0 )
    { }

    // Cleanup
    GSIWorkbook.Close( false );
    // Manual disposal because of COM
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorkbook ) != 0 )
    { }

    myApp.Application.Quit();
    myApp.Quit();
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( myApp ) != 0 )
    { }

    myApp = null;
    GSIWorkbook = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();
    return true;
} // End loadExcel

Upvotes: 0

Views: 1421

Answers (1)

Grantly
Grantly

Reputation: 2556

If you show us your complete usage of your excel object, I bet you will find you are breaking the 2 dot rule. Sounds absurd I know, but I think you are inadvertently creating instances of objects that cannot be disposed by Excel or the GC and then it cannot close properly. (Called Runtime Callable Wrappers)

When you use - say - this code:

xlWorkBook = xlApp.Workbooks.Add

...you are actually causing the problem. You need to create a variable pointing to Workbooks and use that directly and dispose of it. Example from the link:

Dim xlApp As New Excel.Application
Dim xlWorkBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlWorkBook As Excel.Workbook = xlWorkBooks.Add()

....all your code, then

xlApp.Quit()

If Not xlWorkBook Is Nothing Then
    Marshal.FinalReleaseComObject (xlWorkBook)
    xlWorkBook = Nothing
End If
If Not xlWorkBooks Is Nothing Then
    Marshal.FinalReleaseComObject (xlWorkBooks)
    xlWorkBooks = Nothing
End If
If Not xlApp Is Nothing Then
    Marshal.FinalReleaseComObject (xlApp)
    xlApp = Nothing
End If

xlApp.Quit()

See here for details:

http://www.siddharthrout.com/2012/08/06/vb-net-two-dot-rule-when-working-with-office-applications-2/

Upvotes: 3

Related Questions