none
When should I call Marshal.ReleaseComObject?

    Question

  • Hi;

    How do I know when to call ReleaseComObject? Is it anytime I do the safe cast to instantiate a COM object as a C# object?

    And should I even be doing it? According to this (and this) it's generally a bad idea but according to Andrei you should.

    Specifically, when Word passes COM objects in the ribbon menu method calls. I make a safe cast (have to do 2 - 3 to find our what they are - go with the first non-null safe cast) and then use that casted object. Should I be calling release on these when I am done?

    Should Word be cleaning up these context objects after it's passed them in? Or is Word not able to because it's my safe cast that causes the need to release and Word does not know if I did that?

    ??? - thanks - dave


    Who will win The International Collegiate Programming Championships?

    Wednesday, April 25, 2012 12:41 PM

Answers

  • Hi Dave,

    In the first article, Paul discusses using COM objects in a non-isolated add-in. In a shared add-in (it isn't isolated in a separate AppDomain) you should not use Marshal.ReleaseComObject because this may crash other shared add-ins and the host application itself. I talk about this article in a comment to When to release COM objects in Office add-ins developed in .NET.

    In the second article, Eric compares a shared add-in and VSTO add-in. He says that VSTO will unload the AppDomain when the add-in is uloaded and this will release all COM objects. This is true, of course, but have you read Systematically Releasing Objects (this is MSDN)? The fact that VSTO releases everything at shutdown is really nice but you also need to release COM objects at run time.

    Below are some results of leaving a COM object unreleased when automating Office applications:

    On using GC.Collect(). The Rule #1 in When to call GC.Collect() is this:

    Don't.

    In my practice, releasing everything is obviously excessive. For instance, I can't remember anything wrong with leaving Outlook.Namspace objects unreleased. In Word and Excel, leaving COM objects unreleased usually doesn't do any harm until someone runs Word or Excel via Automation with your add-in on. Still, there's no way to know how e.g. Word would react when a given COM object is left unreleased in this or that situation. So, releasing everything is a "safety first" approach. A bore. But it saves your time.

    > Specifically, when Word passes COM objects in the ribbon menu method calls. I make a safe cast (have to do 2 - 3 to find our what they are - go with the first non-null safe cast) and then use that casted object. Should I be calling release on these when I am done?

    I suppose Word (Office) releases the IRibbonControl object passed to a callback; you could try to release it, too - I suppose doing this is safe. But most definitely, you are responsible for releasing the COM object created by accessing the IRibbonCintrol.Context property. When you cast that COM object, this doesn't increase the reference counter.

    In the code below, you release obj only because obj and wnd refer to the same COM object

    dim obj as Object = IRibbonControl.Context
    if (obj is Word.Window) Then
       dim wnd as Word.Window = CType(obj, Word.Window)
       ' your stuff
    end if
    
    Marshal.ReleaseComObject(obj)
    > Should Word be cleaning up these context objects after it's passed them in? Or is Word not able to because it's my safe cast that causes the need to release and Word does not know if I did that?

    When the event handler completes, [I think] Word releases IRibbonControl (remeber, a release just decrements the reference counter). From the view point of Word, this release is safe because if you need to continue using the IRibbonControl after the event, you can just increment the reference counter. But why should Word release the COM object returned by IRibbonControl.Context? In what moment and how can it find out whether you need to use that object later or not? Just imagine: you cache that COM object for later use, Word releases it, and your customers complain that your add-in crashes Word. No, it works in the other way: You create the COM object (by accessing the IRibbonControl.Context property) and, since you know when you don't need it, you are responsible for releasing it.


    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    • Marked as answer by DavidThi808 Thursday, April 26, 2012 3:38 PM
    Thursday, April 26, 2012 9:57 AM

All replies

  • Hi;

    How do I know when to call ReleaseComObject? Is it anytime I do the safe cast to instantiate a COM object as a C# object?

    And should I even be doing it? According to this it's generally a bad idea.

    My specific case is Office (I have written an AddIn) passes COM objects in the ribbon menu method calls. I make a safe cast (have to do 2 - 3 to find our what they are - go with the first non-null safe cast) and then use that casted object. Should I be calling release on these when I am done?

    And shouldt Word be cleaning up these context objects after it's passed them in? Or is Word not able to because it's my safe cast that causes the need to release and Word does not know if I did that?

    ??? - thanks - dave


    Who will win The International Collegiate Programming Championships?

    • Merged by Mike Feng Wednesday, May 09, 2012 5:49 AM duplicate
    Tuesday, April 24, 2012 1:18 PM
  • Reading the link you provided I think the author answers your question in the paragraph below.  He don't say not to use Marshall, but to avoid it

    The lesson here is: If you’re tempted to call “Marshal.ReleaseComObject”, can you be 100% certain that no other managed code still has access to the RCW? If the answer is ‘no’, then don’t call it. The safest (and sanest) advice is to avoid Marshal.ReleaseComObject entirely in a system where components can be re-used and versioned over time. While you may be 100% certain of the way the components work today and believe that a ‘poisoned’ RCW could never be accessed, that belief may be shattered in the future when some of those components’ implementations change.

    -----------------------------------------------------------------------------------------------------------------------

    The real reason for adding the ReleaseComObject is to make sure you don't have any memory leaks.  Many functions allocated memory and you want to make usre that any allocated memory that isn't on your execution stack get removed. So ther are two conditions you want to watch out for

    1) Any Class code created with constuctors gets call with destructors

    2) Any memory that is pass to a dll  doesn't create a memory leak.

    Good programming design is the best solution to a memory leak.  The Marshal.ReleaseComObject is just a secondary method for preventing memory leaks and you don't need to used it.  One issues is it is sometimes very difficult to determine where memory is being allocated in a Visual Studio Application.  So for novices it is problably a good idea to use the Marshal.ReleaseComObject.  For an experience programmer, it may not be necessary to add the extra protection that Marshal.ReleaseComObject provides.


    jdweng

    • Proposed as answer by Mike Feng Thursday, April 26, 2012 6:36 AM
    • Unproposed as answer by DavidThi808 Thursday, April 26, 2012 3:35 PM
    Tuesday, April 24, 2012 1:48 PM
  • Doesn't my casting the COM object to a C# class cause the reference counter for the COM object to be increased by one? If so, if I never call ReleaseComObject will that object persist forever? Or is there some kind of COM garbage clean-up that occurs?

    I think this is my fundamental question - does my casting a COM object to the C# one require me to call release? Everything I've read, including your post above, is not clear on this - which is why I'm asking.

    thanks - dave


    Who will win The International Collegiate Programming Championships?

    Tuesday, April 24, 2012 2:22 PM
  • As I said previously : "The Marshal.ReleaseComObject is just a secondary method for preventing memory leaks and you don't need to used it."  The best way of preventing memory leaks is to design your software so you don't create the leaks in the first place.

    You have to expect that the COM object does it own cleanup and the ReleaseComObject will deallocate any memory that it uses.  The ReleaseComObject will repair any problems on the execution stack.  One common probelm that occurs in the excution stack if the size of the parameter in the calling functon doesn't match the size of the variable in the the function.  the ReleaseComObject will fix the stack after the COM object is called.  Also the ReleaseComObject will rease any local memory that the com object uses becasue it is also on the sttack.

    Not all object are the same size.  You can cast an excel cell (range object) or an excel worksheet to the general class object.  Each object has a differnt number of properties which means a different amount of memory.

    If the memory is inside the program resouces then a garbase cleanup can be run at the end of execution.  But is a program runs for days how do you do a cleanup as the program is running and get back the used memory.  Also if the memory is outside the prgram resources (like a Windows Allocate)  how do you get back that memory from a garbase cleanup.  You need to call a windows deallocate function.


    jdweng

    Tuesday, April 24, 2012 3:02 PM
  • Hi;

    That all makes sense. The issue I face is I don't create the objects and therefore I can't deallocate them. I have an Office AddIn where Word passes me a COM object. That COM object belongs to Word and when I return Word is expecting that the COM object is still good. So I can't deallocate or free it.

    There is also no way for me to tell Word what I did with that object, if anything. In a lot of cases when Word calls me I do nothing with the COM object, I need to know the event occurred, I don't need to know on what object it occurred.

    So that brings me back to my original question. If I cast that COM object to a C# object, does that increase the reference count (ie is there a Marshal call that occurs in that cast)? And if so, should I then call ReleaseComObject to drop the reference count by 1 so that Word will know it can deallocate it?

    Or is there no increase due to my cast and therefore decreasing the reference count by 1 would be a bug because I'm marking something in use as available to free.

    ??? - thanks - dave


    Who will win The International Collegiate Programming Championships?

    Tuesday, April 24, 2012 4:34 PM
  • I think everybody is basically saying the same thing.  Nobody is saying don't use Marshal.ReleaseComObject and nobody is saying always use Marshal.ReleaseComObject.  It depends on a lot of factors and you can't make one general rules that will always appply.

    1) A program is only responsible for the objects/memory it create and can't cleanup a mess made by another program.

    2) Generic fixes like Marshal.ReleaseComObjec will never work 100% of the time.  You can fool some of the people all of the time, you can fool all of the peopele some of the time, but you can't fool all of the people all of the time.

    3) Nothing beats a good software design which should include understanding the features of the code yo use.


    jdweng

    • Proposed as answer by Mike Feng Thursday, April 26, 2012 6:36 AM
    • Unproposed as answer by DavidThi808 Thursday, April 26, 2012 3:35 PM
    Wednesday, April 25, 2012 2:41 AM
  • hi Dave,

    Yes, it is bad idea.  But if you absolutely need to call ReleaseComObject, make sure a COM component gets released at a determined time, you should instead use Marshal.FinalReleaseComObject in Whidbey. This API will release the underlying COM component regardless of how many times it has re-entered the CLR. Comparatively, ReleaseComObject only decrements the internal ref count of the RCW (which is incremented by one every time the COM component re-enters the CLR) and only if it falls to 0 will the underlying COM component be released. On previous versions of the CLR, you can accomplish the same thing that FinalReleaseComObject does by calling ReleaseComObject in a loop until the value returned is 0.


    Regards, http://shwetamannjain.blogspot.com

    Wednesday, April 25, 2012 3:15 AM
  • Nothing beats a good software design which should include understanding the features of the code yo use.

    I agree 100%. That's why I countinue to ask about this specific case. Because in all the discussion above I have not found a clear unambigous answer to my question:

    If I do a cast of a COM object passed to me by Word through the Ribbon API - should I call ReleaseComObject on that object? The object was created by Word but Word does not know that I cast it which I believe marshalls it.

    ??? - thanks - dave


    Who will win The International Collegiate Programming Championships?

    Wednesday, April 25, 2012 12:30 PM
  • I think calling FinalRelease would be a bad idea - what if Word will continue to use that object when I return from the Ribbon call?

    Who will win The International Collegiate Programming Championships?

    Wednesday, April 25, 2012 12:31 PM
  • As I said before, you can't release an object you didn't create.  Word has to take care of that.  If you opened a word application, then close the word application.  Word will take care of releasing its own objects.  If you open a word document, then close the word document.

    Always close or release objects in the opposite order they were opened or created.  Never close or release objects that you did not open or create.


    jdweng

    Wednesday, April 25, 2012 2:07 PM
  • Hi Joel;

    You say absolutely don't release objects I haven't created. But there are numerous people who are experts writing Word Add-Ins (like this) that say you do need to call release on objects Word passes in on events if they are cast to a .net object.

    Correct me if I'm wrong here, isn't the object marshalled and the reference counter increased by one if I cast the COM object to a .net object? If so, I think Word has no way of knowing I did that.

    I'm not trying to be argumentative here but I want to find out what is correct. Can you tell me why you believe I should not call release on these COM objects passed in? There are some who agree with you, but also a lot that disagree - so I want to get to the why so I know for sure what is correct.

    thanks - dave


    Who will win The International Collegiate Programming Championships?

    Wednesday, April 25, 2012 4:56 PM
  • I understand very well the low level functionality of the compiler.  When you "cast to a .net object" all you are doing is creating a pointer (link)  from the net variable  to the word object.  The word object can take up lots of memory.  The net variable is a long pointer.

    When you release the word object you just need to break the link between the word object and the Net Variable and make sure you release the net memory.  You don't want to deallocated the word object which is word responsibility.


    jdweng

    Wednesday, April 25, 2012 5:06 PM
  • Hi Dave,

    Thanks for posting in the MSDN Forum.

    It's based on my experience that we needn't use Marshal.ReleaseComObject in add-in application or document-level application. The GC will handler release issue. When the poor performance of your computer, or your software have a higher memory usage efficiency, you need use Marshal.ReleaseComObject method.

    I hope it can help you,

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, April 26, 2012 7:47 AM
    Moderator
  • Hi Dave,

    In the first article, Paul discusses using COM objects in a non-isolated add-in. In a shared add-in (it isn't isolated in a separate AppDomain) you should not use Marshal.ReleaseComObject because this may crash other shared add-ins and the host application itself. I talk about this article in a comment to When to release COM objects in Office add-ins developed in .NET.

    In the second article, Eric compares a shared add-in and VSTO add-in. He says that VSTO will unload the AppDomain when the add-in is uloaded and this will release all COM objects. This is true, of course, but have you read Systematically Releasing Objects (this is MSDN)? The fact that VSTO releases everything at shutdown is really nice but you also need to release COM objects at run time.

    Below are some results of leaving a COM object unreleased when automating Office applications:

    On using GC.Collect(). The Rule #1 in When to call GC.Collect() is this:

    Don't.

    In my practice, releasing everything is obviously excessive. For instance, I can't remember anything wrong with leaving Outlook.Namspace objects unreleased. In Word and Excel, leaving COM objects unreleased usually doesn't do any harm until someone runs Word or Excel via Automation with your add-in on. Still, there's no way to know how e.g. Word would react when a given COM object is left unreleased in this or that situation. So, releasing everything is a "safety first" approach. A bore. But it saves your time.

    > Specifically, when Word passes COM objects in the ribbon menu method calls. I make a safe cast (have to do 2 - 3 to find our what they are - go with the first non-null safe cast) and then use that casted object. Should I be calling release on these when I am done?

    I suppose Word (Office) releases the IRibbonControl object passed to a callback; you could try to release it, too - I suppose doing this is safe. But most definitely, you are responsible for releasing the COM object created by accessing the IRibbonCintrol.Context property. When you cast that COM object, this doesn't increase the reference counter.

    In the code below, you release obj only because obj and wnd refer to the same COM object

    dim obj as Object = IRibbonControl.Context
    if (obj is Word.Window) Then
       dim wnd as Word.Window = CType(obj, Word.Window)
       ' your stuff
    end if
    
    Marshal.ReleaseComObject(obj)
    > Should Word be cleaning up these context objects after it's passed them in? Or is Word not able to because it's my safe cast that causes the need to release and Word does not know if I did that?

    When the event handler completes, [I think] Word releases IRibbonControl (remeber, a release just decrements the reference counter). From the view point of Word, this release is safe because if you need to continue using the IRibbonControl after the event, you can just increment the reference counter. But why should Word release the COM object returned by IRibbonControl.Context? In what moment and how can it find out whether you need to use that object later or not? Just imagine: you cache that COM object for later use, Word releases it, and your customers complain that your add-in crashes Word. No, it works in the other way: You create the COM object (by accessing the IRibbonControl.Context property) and, since you know when you don't need it, you are responsible for releasing it.


    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    • Marked as answer by DavidThi808 Thursday, April 26, 2012 3:38 PM
    Thursday, April 26, 2012 9:57 AM
  • I think the answers by Andrei (he says yes) and Tom (he says no, unless you need memory, then yes) - http://social.msdn.microsoft.com/Forums/en-US/worddev/thread/3f9625a2-779e-42e8-beb7-41d8c85eb3ff/ point to you do need to release. Or better put, you should if you don't want to leave a bunch of memory used up by objects no longer needed when someone uses Word all week long without ever exiting it.

    I'm waiting on an answer from a contact in the Word group for a final, from the Office dev group answer. I'll post that here once I get it.

    thanks  - dave


    Who will win The International Collegiate Programming Championships?

    Thursday, April 26, 2012 3:40 PM
  • Hi Dave,

    I just searched this thread, does the Office group give a response?

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Tuesday, May 08, 2012 8:00 AM
  • Hi Ghost;

    So far no answer from Microsoft.

    sorry - dave


    Who will win The International Collegiate Programming Championships?

    Tuesday, May 08, 2012 12:23 PM
  • It is sad. They may not notice your thread, how about repost one on that forum?

    Have a lucky day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Tuesday, May 08, 2012 1:33 PM
  • I've posted in the Word forum, I've contacted a program manager at Microsoft, and I've contacted a V.P. at Microsoft. All to no avail.

    Who will win The International Collegiate Programming Championships?

    Tuesday, May 08, 2012 2:28 PM
  • Hi David,

    Because this issue is more related to Office add-in, so I merged this thread to your thread in Word one.

    Thank you for your understanding and support.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, May 09, 2012 5:48 AM