Click here to Skip to main content
15,568,681 members
Articles / Programming Languages / Visual Basic
Posted 6 Mar 2005


48 bookmarked

COM Interoperability in .NET Framework: Part I

Rate me:
Please Sign up or sign in to vote.
4.75/5 (17 votes)
6 Mar 20055 min read
Using COM components in .NET framework.


In this article, we review the concepts and walk-through an example that demonstrates COM interoperability in .NET framework.

What is the need for Interoperability?

COM components have a different internal architecture from .NET components, hence they are not innately compatible. Most organizations, which have built their enterprise applications on COM objects for their middle tier services, cannot write off the investments on these solutions. These legacy components ought to be exploited by managed code in the .NET framework. This is where Interoperability pitches in; it’s a Runtime Callable Wrapper (RCW) that translates specific calls from managed clients into COM specific invocation requests on unmanaged COM components. The method call on RCW will make .NET components believe that they are talking to just another .NET component.

Before we move on to the core concepts, let’s have a small primer on COM.

What is COM?

COM stands for Component Object Model, which is a binary specification for software code re-use. It imposes a standard for the interfaces through which client code talks to component classes. The component’s IUnknown interface helps to maintain a reference count of the number of clients using the component. When this count drops down to zero, the component is unloaded. All components should implement the IUnknown interface. The reference count is maintained through IUnknow::AddRef() and IUnknow::Release() methods, and interface discovery is handled through IUnknow::QueryInterface().

What is Runtime Callable Wrapper?

A .NET application communicates with a COM component through a managed wrapper of the component called Runtime Callable Wrapper. It acts as managed proxy to the unmanaged COM component.

Image 1

When we make a method call, it goes onto RCW and not the object itself. RCW manages the lifetime management of the COM component.

How is the Component Binding in interoperability?

Binding refers to information on methods, properties, events etc. that a client needs to know about the object. We still can use the good old technique of bindings in .NET interoperability viz., Early and Late bindings.

  • Early binding: Clients obtain compile time type information from the component’s type library.
  • Late binding: Clients lack rich type information of the object, it is known at runtime.

How do we implement COM Interoperability?

We can implement it in the following steps:

  • Create Runtime Callable Wrapper out of a COM component.
  • Reference the metadata assembly DLL in the project and use its methods and properties.

Step 1:

There are two ways to generate a managed metadata wrapper:

  • Using Type Library Importer utility.

Type Library Importer (tlbimp.exe) is a command line syntax, which converts COM specific type definition in a COM type library into equivalent definitions for a .NET wrapper assembly. By default, the utility gives the wrapper assembly the same name as the COM DLL.

Image 2

The above example generates a metadata assembly with the name “InteropExampleRCW.dll” out of the COM component “InteropExample.dll” using the following syntax at VS.NET command prompt:

tlbimp  InteropExample.dll  /output:InteropExampleRCW.dll /verbose

Note: it internally resolves ADODB references in the COM. Through “out” argument, we can specify the desired assembly name.

Type library importer interrogates the COM DLL’s type library and translates the information therein into .NET format. The metadata assembly so generated contains wrapper classes that can be used in any .NET client, e.g., C# Windows clients. RCW is created on the fly whenever a component is created and it acts like managed types to COM specific data types.

VS.NET IDE also helps us generate a metadata assembly:

Click on Project -> Add reference -> COM tab

Image 3

The tab lists registered components on the local machine, selects the desired COM DLL and adds to the list of selected components. VS.NET automatically generates a metadata assembly putting the classes provided by that component into a namespace with the same name as the COM DLL.

How is the structure of a Wrapper Assembly?

For each class imported into a wrapper assembly, two wrapper classes are generated. COM specific information can be viewed using MSIL Disassembler utility (ildasm.exe) at VS.NET command prompt:

ildasm InteropExampleRCW.dll

Image 4

InteropExample.dll (developed in VB 6.0) component has the following public classes:

  • Authors
  • Titles

The generated assembly has four classes:

  • Authors
  • AuthorsClass
  • Titles
  • TitlesClass

First is the interface having the same GUID as the original COM class, second is a concrete class whose instance is to be created. Concrete class is suffixed with the word “Class”. Concrete class implements all the interfaces that are supported by the original COM class.

All the generated types are placed under the single namespace InteropExampleRCW.

Step 2

Reference the metadata assembly DLL in the project and use its methods and properties:

Image 5

Create a new C# Windows application project. Drag the following Label, TextBox and DataGrid controls on the form, and name them accordingly; the form will appear as follows:

Image 6

Import the required assemblies:

using System.Data;
using System.Data.OleDb;

Include the following code in the appropriate click events:

To use Authors search from AuthorClass, have code for Search Author button click event as:

private void btnSearchAuthors_Click(object sender, System.EventArgs e)
 //create an instance of AuthorsClass from wrapper assembly
 InteropExampleRCW.AuthorsClass myAuthorRCW = 
              new InteropExampleRCW.AuthorsClass();
 DataSet dsAuthorList=new DataSet("Authors");

 OleDbDataAdapter daAuthRecs=new OleDbDataAdapter();
 ADODB.Recordset rsAuthors=new ADODB.Recordset(); 

//invoke method from the RCW



To use Titles search from TitleClass, code for Search Title button click event:

private void btnSearchTitle_Click(object sender, System.EventArgs e)
  InteropExampleRCW.TitlesClass  myTitlesRCW = 
               new InteropExampleRCW.TitlesClass();

  DataSet dsTitleList=new DataSet("Titles");

  OleDbDataAdapter daTitleRecs=new OleDbDataAdapter();

  ADODB.Recordset rsTitles=new ADODB.Recordset(); 


The output of the run will look like:

Image 7

How Do I Release COM objects?

Runtime Callable Wrapper is managed creation itself; hence its lifetime is controlled by Common Language Runtime. The COM component is freed from memory when the garbage collector calls the Finalize() method on RCW. Internally, RCW calls Release() of IUknown interface on the COM object.

To explicitly remove COM objects from memory, invoke the static method on Marshal class in System.Runtime.InteropServices namespace:

using System.Runtime.InteropServices;


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Written By
Web Developer
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

QuestionTlbImp fails on C++ dll : "not a valid type library" Pin
charles9228-Aug-13 20:17
charles9228-Aug-13 20:17 
I created a minimal Visual Studio 6 Win32 Dynamic Link library project and it built successfully. However when I try to run TlbImp as described above, I get the error message that the dll "is not a valid type library"

I then created a minimal "ATL COM AppWizard" project in VS 6, and was able to run TlbImp to create the RCW dll. However, when I reference the RCW dll in the C# project, none of C++ methods seemed to be available.

Does anyone know how to create a C++ dll that can be used instead of the VB example in this article? (I presume VC 6.0 would have to be used rather than VS 2010 to demonstrate the technique in this article)

Thanks in advance.

P.S. A minor error in the article is that the TlbImp switch is "/out", "/output"

modified 9-Aug-13 17:42pm.

QuestionConflicting Names for Classes and Interfaces Pin
Hassan R. Bhatti17-Sep-12 10:27
Hassan R. Bhatti17-Sep-12 10:27 
GeneralMy vote of 4 Pin
Shanmugam R P14-Sep-12 9:26
Shanmugam R P14-Sep-12 9:26 
NewsSuper Pin
rasheed197921-May-06 6:29
rasheed197921-May-06 6:29 
GeneralThanks Pin
WebMaster6-Mar-05 23:32
WebMaster6-Mar-05 23:32 

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.