Does matter COM object not assigned to var is not released?

89 Views Asked by At

Will be all unmanaged COM objects released in case if I use code like this

var worksheet = new Application().Workbooks.Add().Worksheets.Add();
Marshal.ReleaseComObject(worksheet);

instead of code like this

var excel = new Application();
var workbook = excel.Workbooks.Add();
var worksheet = workbook.Worksheets.Add();
Marshal.ReleaseComObject(excel);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(worksheet);

?

If there is some documentation please send a link in answer.

1

There are 1 best solutions below

3
EJoshuaS - Stand with Ukraine On

Actually, both code samples will leave an Excel process running in the background. You need to call Application.Quit() on the application object, for example. The following works:

private static void DoExcel()
    {
        var application = new Application();
        var workbook = application.Workbooks.Add();
        var worksheet = workbook.Worksheets.Add();

        // Name that this will be saved as
        string name = workbook.FullName + ".xlsx";

        string fullPath = Path.Combine(Directory.GetCurrentDirectory(), name);
        // If a file of the same name exists, delete it so that we won't be prompted if
        // we want to overwrite it when we save
        if (File.Exists(fullPath))
            File.Delete(fullPath);

        // Save the workbook - otherwise we may be prompted as to whether we want to save when we go to quit
        workbook.Save();

        // Quit the application
        application.Quit();

        // Release the references
        Marshal.ReleaseComObject(worksheet);
        Marshal.ReleaseComObject(workbook);
        Marshal.ReleaseComObject(application);

        // Release the .NET reference and run the garbage collector now to make sure the application is closed immediately
        worksheet = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

A few other good things to remember: I didn't use it here, but there's a Marshal.FinalReleaseComObject method that's very useful in these cases. Also, again I didn't use this in my code sample, but the Marshal.ReleaseComObject method returns the current count, so you could always do the release in a loop if you wanted to make sure the count reached zero:

while (Marshal.ReleaseComObject(comObject) > 0) { }

You can also use this for debugging purposes - e.g.

int count = Marshal.ReleaseComObject(comObject);
Trace.TraceInformation("Current COM object reference count: " + count.ToString());