none
Releasing COM Objects RRS feed

  • Question

  • Hi,

     

    I just started with vb.net and I am not really familiar with releasing COM object yet.

    I am using Visual Studio 2015 and my program is for Office 2007 and above.

    So I am trying to do it perfect but I am not sure if this is the correct way to release COM objects.

    Example:

     [...]

    If ActiveWindow IsNot Nothing Then

        Marshal.ReleaseComObject(ActiveWindow.SELECTION.ShapeRange)

        Marshal.ReleaseComObject(ActiveWindow.SELECTION)

        Marshal.ReleaseComObject(ActiveWindow)

        ActiveWindow = Nothing

    End If

     [...]

    1. Is it necessary to release each level separately?

    Seen here: http://www.codeproject.com/Tips/235230/Proper-Way-of-Releasing-COM-Objects-in-NET

    1. Is it “dangerous” to use more than two dots at a time when working with COM objects (ActiveWindow.SELECTION.ShapeRange) - Or should I assign each level to a seperate variable?

    Seen here: http://www.siddharthrout.com/2012/08/06/vb-net-two-dot-rule-when-working-with-office-applications-2/

    1. Is there a way to check at the end of each function – at least in debugging mode – if there is any COM object left behind and not released yet?

    Many thanks.

    Wednesday, November 4, 2015 2:37 PM

Answers

  • COM objects that reach managed code get wrapped in something called a 'Runtime Callable Wrapper" (RCW). Each time the runtime sees the same com object, it reuses the same RCW and that RCW keeps a count of how many times it was passed in. Marshal.ReleaseComObject() will decrement the count and release the com object if it hits 0 (or if the RCW gets collected and finalised).

    In your code, you request the SELECTION twice but only release it once. Even in the case of ShapeRange, you request it once and then release it once with no net effect on the count.

    To answer your specific questions:

    1. I'm not familiar with this particular COM API, but if these objects haven't already entered the runtime, then you shouldn't need to release them. And if they have, you should release them using whatever field/variable you have holding them.

    2. Not really, you won't have a reference to the RCW to release it, but it will still be released eventually by the GC. If the only native resource held by the COM object is native memory, then you might not care. If you reach a point where you KNOW you won't need it anymore, then you can use Marshal.FinalReleaseComObject() to release it regardless of the count, but need to be sure, if you try to access the RCW after the underlying com object is released then it will throw an InvalidComObjectException.

    3. You might be able to use the ICorDebug api to enumerate all the objects in the process and check if any of them are RCW's (if the ICorDebugValue implements ICorDebugComObjectValue then it's an RCW). I'm not aware of any debuggers that do this for you.

    Wednesday, November 4, 2015 9:15 PM