Reputation: 37
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
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