Click here to Skip to main content
15,867,568 members
Articles / Operating Systems / Windows

.NET and COM interop story

Rate me:
Please Sign up or sign in to vote.
3.75/5 (3 votes)
2 Jun 2009CPOL2 min read 16.4K   8   3
Let's see a short example using COM objects exposed by Internet Explorer. The code below changes the color of every link in an HTML document.

.NET allows programmers to reuse COM components in their managed code. To make this possible, a managed wrapper object around the native object is needed. Besides that, one can use the COM object like any other managed object. Even if it sounds simple, you have to be aware of the differences between the CLR's object lifetime management and the COM version of object lifetime management.

COM programmers have to call Release on every interface that has been AddRef'ed. For C# programmers using COM objects, that means AddRef is called when:

  • a COM object is created
  • a COM object is returned by calling a method or a property
  • a COM object is cast'ed to another COM interface type

To release a COM object in C#, there are two options:

  • Leave the GC to collect managed wrappers and to call their finalizers that will call Release on native COM object
  • Manually call Marshal.ReleaseComObject on every interface used in the code

Let's see a short example using COM objects exposed by Internet Explorer. The code below changes the color of every link in an HTML document.

C#
// IHTMLDocument2 doc;
foreach (IHTMLElement elem in doc.all)
{
    IHTMLAnchorElement anchor = elem as IHTMLAnchorElement;
    if (anchor != null)
    {
        elem.style.color = "red";
    }
}

This first approach leaves the task of releasing COM objects to garbage collector. Let's manually release COM objects now:

C#
// IHTMLDocument2 doc;
IHTMLElementCollection allCollection = doc.all;
foreach (IHTMLElement crntElem in allCollection)
{
   IHTMLAnchorElement anchor = crntElem as IHTMLAnchorElement;
   if (anchor != null)
   {
       IHTMLStyle style = crntElem.style;
       style.color = "red";

       Marshal.ReleaseComObject(style);
       Marshal.ReleaseComObject(anchor);
   }

   Marshal.ReleaseComObject(crntElem);
}

Marshal.ReleaseComObject(allCollection);

As you can see, the number of code lines doubles! I personally prefer to leave the task of releasing COM objects to GC even if they will be eventually released after some time when GC comes into action.

Some might be tempted to call GC.Collect after a large chunk of code that works with COM objects but this could be even worse because other managed objects could be promoted to next GC generation and their lifespan is therefore longer than necessary.

In theory, it is possible to create a lot of large COM objects that will exceed the native heap while the managed heap has a lot of available memory because managed wrappers are smaller in size. GC won't be called in this scenario so the native heap won't be freed.


If your application suffers from this kind of memory allocation problem, maybe using COM objects from managed code is not the best approach for you.

This article was originally posted at http://codecentrix.blogspot.com/feeds/posts/default

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Codecentrix Software
Romania Romania
Software consultant in Bucharest Romania writing Windows programs and browsers plug-ins since 1998 with Visual C++.

Comments and Discussions

 
GeneralWell... Pin
Vitaly Tomilov3-May-10 9:06
Vitaly Tomilov3-May-10 9:06 
GeneralRe: Well... Pin
Adrian Dorache3-May-10 21:53
Adrian Dorache3-May-10 21:53 
Generalgood work Pin
Donsw27-Jul-09 17:11
Donsw27-Jul-09 17:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.