As far as I can see, this is not a duplicate question, as the question here is about why the accepted answers of seemingly duplicate questions, do not solve my issue in what appears to be the same circumstances.
For days, I have been struggling with my application failing to end instances of Excel, which have been opened using interops.
My application opens and closes Word applications just fine (i.e. the process disappears from task manager), but not Excel apps. Excel always remains open in the task manager. After much, much searching - this seems to be the definite guide on how to close Excel instances. However, if I copy and paste that exact example code - and run it as a console app, in either .NET Framework, or .NET 6 - Excel still fails to close, exactly as per the behaviour of my application.
Presumably, this must be an issue with the latest/newer versions of Word?
Completely and utterly lost on this one...
Code from the above link that leaves Excel open:
using System;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
namespace TestCsCom
{
class Program
{
static void Main(string[] args)
{
// NOTE: Don't call Excel objects in here...
// Debugger would keep alive until end, preventing GC cleanup
// Call a separate function that talks to Excel
DoTheWork();
// Now let the GC clean up (repeat, until no more)
do
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
while (Marshal.AreComObjectsAvailableForCleanup());
}
static void DoTheWork()
{
Application app = new Application();
Workbook book = app.Workbooks.Add();
Worksheet worksheet = book.Worksheets["Sheet1"];
app.Visible = true;
for (int i = 1; i <= 10; i++) {
worksheet.Cells.Range["A" + i].Value = "Hello";
}
book.Save();
book.Close();
app.Quit();
// NOTE: No calls the Marshal.ReleaseComObject() are ever needed
}
}
}
app.Workbooks.Add
,worksheet.Cells.Range
, etc. IMHO the old "no two dots" rule is still valid. You shouldMarshal.ReleaseComObject
every ole reference. The GC might try to release every object, but this can still cause issues with excel. And if all else fails, kill the process yourself. – Usknull
each object you have declared. You can do it in any order, but if you do it in the reverse order of declaration, you cause the Excel Process to close immediately, otherwise it will persist a bit longer (and your do / while loop will iterate more times) -- You can actually do the same thing withMarshal.ReleaseComObject()
+Marshal.FinalReleaseComObject()
+Marshal.CleanupUnusedObjectsInCurrentContext()
, but it's quite prone to fail – Initiateworksheet.Cells.Range["A" + i].Value = "Hello";
initializes a Range. In Office 16 it's not a problem. In Office 365 it could be. Note that you always need to test it running the executable, never in Visual Studio, even less in debug mode – Initiate.xlsx
files you might consider using OpenXML libraries like SpreadSheetLight which do not have the release issue as with interop method to work with Excel. If interested I can post code for this method. – Fount