tags:

views:

95

answers:

1

Recently I spent quiet some time writing various Visual Studio Extensions projects. Even though the projects are all managed code to access the core VS services it is still necessary to work with the old style COM interfaces.

Here is an example :

var selectionTracker = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection));
IntPtr ppHier;
uint pitemid;
IVsMultiItemSelect ppMIS;
IntPtr ppSC;
selectionTracker.GetCurrentSelection(out ppHier, out pitemid, out ppMIS, out ppSC)))

as you can see this call returns 2 pointers (ppHier and ppSC) and an object ppMIS. The question is: how should I go about playing it nice with COM reference counting.

It is my understanding that in COM world when a method returns a pointer to an object this pointer is AddRef'ed before it is returned. Which means that to prevent the COM object leakage I have to Release them when I am done using them.

I also assume that what I am getting as an object it is already wrapped into a RCW, which will take care of reference releasing when it is finalized.

These 2 assumptions applied to the above call would mean that I have to make sure to call `Marshal.Release' on my 2 pointers, but I should not do anything about reference counting in regards to the object returned.

To rephrase my question: assuming that the COM objects I am using are playing by the COM rules, is the approach above the right way to deal with COM reference counting?

A: 

In this particular scenario you would need to call Marshal.Release on the IntPtr variables otherwise they will not go away. Of course if you tell the marshaller to just use object (or a specific type) directly then you would not need to worry about it as the RCW will ensure the object is destroyed at some point in the future (i.e. when the finalizer is called in the garbage collection process).

Of course the finalizer approach could happen at a non-deterministic point in time so if the object maintains some resource which you need to get rid of you should ideally call Marshal.ReleaseComObject to decrement its reference count before the wrapper does the releasing for you.

tyranid