You need to have a good understanding of the Runtime Callable Wrapper in order to use COM with .Net. Basically, everything you have in your .Net code that is a reference to a COM object, is really a reference to an RCW. The RCW manages the reference count on the underlying COM object by counting how many references are to it, and when the reference count on it drops to 0, it will call Release
(once) on the underlying object. While the RCW is live, it will maintain a single reference on the COM object.
The ReleaseComObject
API will decrease the reference count on the RCW by 1. If this brings the reference count on the RCW to 0, then the RCW will call Release
on the COM object, otherwise not. There is also FinalReleaseComObject
which will cause the reference count on the RCW to go to 0 (thus cause the RCW to call Release
) although this is kind of risky if you have other references outstanding on the RCW as they will probably error.
"Normally", the references on the RCW are managed when the objects which have a reference to it are garbage collected - this would explain why you saw the COM object be released when you forced the garbage collection. This, combined with what we know about how the RCW works tells us that there were other references on the RCW that you also would have "needed" to call ReleaseComObject
on in order to cause it to Release
.
Calling ReleaseComObject
is kind of an end run around the .Net runtime, and you have to be super careful to manage all of the references that are created. Some of the references that are created are "implicit" references - these come about because of doing things like calling into properties which return references which you then call in on. This is sometimes refered to as the "too many dots" problem, when you do something like this:
object.foo.blah.baz.something()
The "foo", "blah" and "baz" are probably all references to some COM object somewhere that you need to think about.