none
Release COM objects when developing Excel add-ins with .NET? RRS feed

  • Question

  • I am developing an Excel COM add-in that is written in VB.NET. To my help I have Visual Studio, VSTO and Add-in Express.

    I have read here and there that I need to release COM objects using Marshal.Release.

    My previous experience is from VBA for Excel and there I never needed to release variables. When a subroutine ended, variables were automatically released for me.

    Why is this different when writing an add-in in VB.NET?

    Tuesday, January 13, 2015 11:24 AM

Answers

  • Hello,

    There is a difference between VBA and VB.NET. Because now you develop an external application (an add-in in your case) which is called by the Office application. All communications are based on the COM interfaces. The second thing is that you develop a managed application on top of the .Net framework.

    You may find the following links helpful:

    Systematically Releasing Objects - is related to Outlook, but the same principles can be applied to any other Office application.

    When to release COM objects in Office add-ins developed in .NET

    Tuesday, January 13, 2015 12:01 PM
  • Hi Eugene,

    I completely agree with you.

    Calling Excel from a background thread is a recipe for trouble. As explained in the first post you link to, the fix is to get the calls back onto the main Excel thread. For an Excel add-in (which this question is about), with the code running on the main thread, you should never run into the problem where Excel does not quit.

    Even when automating Excel from another thread or a separate process (as in Andrei's post - your second link), my suggestion is to rely on Andrei's "Strategy #2" which relies on the .NET GC, rather than on "Strategy #3" which uses Marshal.ReleaseComObject(). Our only disagreement is for this preference - Andrei suggests that "Strategy #3" with the Marshal.ReleaseComObject() is best, but in practice I've found it unworkable and unnecessary. The difficulties that Andrei suggests for using the GC to clean up are in my opinion far fewer than the difficulties in doing the explicit reference clean-up (including detached COM RCW and the like).

    (One Office COM wrapper library that does explicit tracking of all the references, so that it can help doing explicitly clean up, is NetOffice.)

    You're absolutely right that one sometimes needs to call GC.Collect() twice to ensure that circular references are disconnected and finalized correctly.

    After all I stick to my view that calling Marshal.ReleaseComObject() is a silly anti-pattern - certainly in the context of this question, and in my opinion even in the more problematic cases where Excel is automated from another process.

    -Govert

    Excel-DNA - Free and easy .NET for Excel


    Thursday, January 15, 2015 6:28 PM

All replies

  • Hello,

    There is a difference between VBA and VB.NET. Because now you develop an external application (an add-in in your case) which is called by the Office application. All communications are based on the COM interfaces. The second thing is that you develop a managed application on top of the .Net framework.

    You may find the following links helpful:

    Systematically Releasing Objects - is related to Outlook, but the same principles can be applied to any other Office application.

    When to release COM objects in Office add-ins developed in .NET

    Tuesday, January 13, 2015 12:01 PM
  • If your add-in code is running on the main Excel thread (e.g. from a COM object event handler or a ribbon callback event), then you need not worry about releasing any Excel COM objects at all.

    If you have to access the Excel COM object model from other threads, you're better off explicitly calling the .NET garbage collector to do the COM cleanup than trying to keep track of all the COM references yourself.

    You will know that something has gone wrong if the Excel.exe process stays alive (check in Task Manager) after you close the Excel window.

    Nearly everything you read on the web about Marshal.ReleaseComObject and stuff related to 'two dots' is complete misinformation. The .NET runtime actually manages COM reference counting perfectly well.

    -Govert

    Excel-DNA - Free and easy .NET for Excel
    Wednesday, January 14, 2015 9:36 PM
  • Hi Govert,

    I completely disagree with you. I can provide a lot of well-known issue with Excel related to not releasing underlying COM objects. For example, take a look at the Back from a bug hunt [or, Don’t Call Excel on a Background Thread] one. Another one was written by my colleague - Why doesn’t Excel quit? .

    > The .NET runtime actually manages COM reference counting perfectly well.

    It is true. But references are released when the GC is run. To swipe the heap and release references you have to run the GC.Collect method twice explicitly.

    Thursday, January 15, 2015 5:02 PM
  • Hi Eugene,

    I completely agree with you.

    Calling Excel from a background thread is a recipe for trouble. As explained in the first post you link to, the fix is to get the calls back onto the main Excel thread. For an Excel add-in (which this question is about), with the code running on the main thread, you should never run into the problem where Excel does not quit.

    Even when automating Excel from another thread or a separate process (as in Andrei's post - your second link), my suggestion is to rely on Andrei's "Strategy #2" which relies on the .NET GC, rather than on "Strategy #3" which uses Marshal.ReleaseComObject(). Our only disagreement is for this preference - Andrei suggests that "Strategy #3" with the Marshal.ReleaseComObject() is best, but in practice I've found it unworkable and unnecessary. The difficulties that Andrei suggests for using the GC to clean up are in my opinion far fewer than the difficulties in doing the explicit reference clean-up (including detached COM RCW and the like).

    (One Office COM wrapper library that does explicit tracking of all the references, so that it can help doing explicitly clean up, is NetOffice.)

    You're absolutely right that one sometimes needs to call GC.Collect() twice to ensure that circular references are disconnected and finalized correctly.

    After all I stick to my view that calling Marshal.ReleaseComObject() is a silly anti-pattern - certainly in the context of this question, and in my opinion even in the more problematic cases where Excel is automated from another process.

    -Govert

    Excel-DNA - Free and easy .NET for Excel


    Thursday, January 15, 2015 6:28 PM