Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  Upgrading  »  .NET Interoperability - Calling a .NET Component from a COM Component
 »  Home  »  Windows Development  »  Interop  »  .NET Interoperability - Calling a .NET Component from a COM Component
.NET Interoperability - Calling a .NET Component from a COM Component
by Ashish Jaiman | Published  03/28/2002 | Upgrading Interop | Rating:
Ashish Jaiman

Ashish works as a Sr. Software Developer with Lexign Inc., an end-to-end trusted electronic transaction management software provider (

Ashish has 6 years of experience in designing and developing distributed systems, server technologies and web based software applications using Microsoft technologies, Java, XML and .NET. He holds MCSD (Microsoft Certified Software Developer) and SCJP (Sun Certified Java Programmer) certifications.

Contact Ashish at or


View all articles by Ashish Jaiman...
.NET Interoperability - Calling a .NET Component from a COM Component

Article source code:

When a COM client calls a .NET object, the .NET Framework will create a COM callable wrapper (CCW). COM clients use the CCW as a proxy for the managed object. The role of CCW is to marshal calls between managed and unmanaged code and also to manage object identity and object lifetime of the managed objects they wrap.

The purpose of this article is to create a demo project to show how to call .NET component from COM client and to implement events raised by the .NET component. The example we create uses .NET component and COM client extending the functionality of the .NET component using delegation.

Step 1

Let's start by creating a Strong Name for the .NET component we will be creating in next steps. Signing an assembly with a strong name helps .NET ensure that the code in the assembly has not been changed since the assembly was published. Strong name is a unique name created by hashing a 128-bit encryption key against the name of the Assembly (COMInterOp in our case). To create a strong name, you can use the sn tool.

To create a key file named COMInterOp.snk, you could use this command line:

sn -k COMInterOp.snk

Step 2

Now we are going to create a .NET Assembly. Our assembly has only one class CEmp that exposes properties (FirstName, LastName, DOB) and raises an event (Senior).

Raising event from .NET Component and consuming it in COM component is done by defining event sink interface in managed code and then apply the ComSourceInterfacesAttribute to connect the event sink interface to the managed class.

Here is the command line instruction to create an assembly using the strong name (for vbc switches info see MSDN)

vbc /out:COMInterOp.dll /t:library /keyfile:COMInterOp.snk CEmp.vb VB.NET CEmp class code
Imports System
Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices

<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface evtSenior
    Sub Senior()
End Interface

<ComSourceInterfacesAttribute("evtSenior")> _
Public Class CEmp
    Private mstrFirstName As String
    Private mstrLastName As String
    Private mdtDOB As Date
    Public Event Senior()
    Public Property FirstName() As String
            FirstName = mstrFirstName
        End Get
        Set(ByVal Value As String)
            mstrFirstName = Value
        End Set
    End Property
    Public Property LastName() As String
            LastName = mstrLastName
        End Get
        Set(ByVal Value As String)
            mstrLastName = Value
        End Set
    End Property
    Public Property DOB() As Date
            DOB = mdtDOB
        End Get
        Set(ByVal Value As Date)
            mdtDOB = Value
            If DateDiff(DateInterval.YearValueNow> 60 Then
                RaiseEvent Senior()
            End If
        End Set
    End Property
End Class
Generated using PrettyCode.Encoder

Step 3

Once the assembly is created we have to create a Type library so the COM client can use the Assembly seamlessly. We have following options of packaging assembly for COM:

  • Type Library Exporter
    Using the Type Library Exporter (Tlbexp.exe) the classes and interfaces contained in an assembly are converted into to a COM type library. Once the TypeLib is created COM clients can create an instance of the .NET class and call the methods of that object, just as if it were a COM object.
  • TypeLibConverter Class
    The TypeLibConverter Class of the System.Runtime.InteropServices namespace provides methods to convert an assembly to a TypeLib. This API produces same output as Tlbexp.exe
  • Assembly Registration Tool
    The Assembly Registration Tool (Regasm.exe), reads the metadata within an assembly and adds the necessary entries to the registry, which allows COM clients to create .NET Framework classes transparently. The Assembly Registration tool can generate and register a type library when you apply the /tlb: option. COM clients require that type libraries be installed in the Windows registry. Without this option, Regasm.exe only registers the types in an assembly, not the type library. Registering the types in an assembly and registering the type library are distinct activities.
  • The .NET Services Installation Tool (Regsvcs.exe) (see MSDN for more info)

In our example we will use the RegAsm.exe to create TypeLib from the classes and interfaces definitions in our COMInterOp.dll assembly.

From the command line run

regasm ComInterOp.dll /tlb:ComInterOp.tlb

Step 4

Now the .NET component (COMInterOp.dll) should be installed in the GAC (global assembly cache) to work with the COM code.

The command line instruction to install COMINterOp.dll in GAC is

dir>Gacutil -i COMInterOp.dll

Step 5

To use the .NET assembly, as it was a COM component, add reference to the TypeLib from the COM component project created in the previous steps and code against it by creating CEmp object and delegation the calls to this object.

The COM Client has two classes CEmp and CEmps, CEmp is a wrapper over our .NET assembly's CEmp and exposes FirstName, LastName and IsSenior properties. The FirstName, LastName properties just delegates to the properties of .NET's CEmp but IsSenior uses the event raised by the .NET assembly to set its value. The CEmps class is a collection of CEmps and exposes methods to test our code.

COM Component
'Class Emps
Option Explicit

Private Emps As Scripting.Dictionary

Private Sub Class_Initialize()
  Set Emps = New Scripting.Dictionary
  Dim objEmp As CEmp
  Set objEmp = New CEmp
  objEmp.InitMe "John""Doe""01/01/1970"
  Emps.Add 0objEmp
  Set objEmp = New CEmp
  objEmp.InitMe "Mike""Edwards""01/01/1941"
  Emps.Add 1objEmp
  Set objEmp = New CEmp
  objEmp.InitMe "Debra""Bunn""01/01/1930"
  Emps.Add 2objEmp
End Sub

Public Function PrintEmps() As String
  PrintEmps = PrintBool(True& PrintBool(False)
End Function

Public Function PrintBool(ByVal xblnSeniors As BooleanAs String
  Dim intCount As Integer
  Dim objEmp As CEmp
  Dim strPrint As String
  For intCount = 0 To Emps.Count - 1
    Set objEmp = Emps(intCount)
    If xblnSeniors = objEmp.IsSenior Then
      strPrint = strPrint & PrintEmp(objEmp& Chr(13)
    End If
  Next intCount
  PrintBool = strPrint
End Function

Private Function PrintEmp(ByVal xobjEmp As CEmpAs String
  Dim strPrint As String
  strPrint = xobjEmp.FirstName & Chr(9& xobjEmp.LastName
  PrintEmp = strPrint
End Function
'End Class Emps

'Class Emp
Option Explicit

Private mblnIsSenior As Boolean
Private WithEvents mobjEmp As ComInterOp.CEmp

Public Sub InitMe(ByVal xstrFName As String_
    ByVal xstrLName As StringByVal xdtDOB As Date)
  Set mobjEmp = New ComInterOp.CEmp
  With mobjEmp
    .FirstName = xstrFName
    .LastName = xstrLName
    .DOB = xdtDOB
  End With
End Sub

Public Property Get FirstName() As String
  FirstName = mobjEmp.FirstName
End Property

Public Property Get LastName() As String
  LastName = mobjEmp.LastName
End Property

Public Property Get IsSenior() As Boolean
  IsSenior = mblnIsSenior
End Property

Private Sub mobjEmp_Senior()
  mblnIsSenior = True
End Sub
'End Class Emp
Generated using PrettyCode.Encoder

Related Articles

.NET Interoperability - Calling COM Components from .NET

How would you rate the quality of this article?
1 2 3 4 5
Poor Excellent
Tell us why you rated this way (optional):

Article Rating
The average rating is: No-one else has rated this article yet.

Article rating:3 out of 5
 57 people have rated this page
Article Score31740
Sponsored Links