March 8, 2021
Hot Topics:

COM Interoperability and .NET

  • By Mark Strawmyer
  • Send Email »
  • More Articles »

Use a Managed .NET Object in an Unmanaged COM Application

There are several reasons why you may want to use a .NET object in a COM application. A likely scenario is that you are making changes to an existing COM component and you want to leverage some new functionality that was built using .NET.

If you intend to call .NET objects from COM, there are a few items to remember due to the different capabilities of .NET and COM. A list of some of the items is outlined below.

  • Do not use parameterized constructors.
  • Do not rely on the constructor to have been called prior to other method invocations.
  • Do not use static methods.
  • The .NET object needs to be strong named and resolvable at runtime.
  • Assign GUIDs to all .NET objects so that the appropriate COM required registry entries can be created. The GUIDs are assigned to the .NET object by adding the System.Runtime.InteropServices.Guid attribute to the class definition. The GUID can be generated in Visual Studio .NET by going to the Tools menu and select the Create GUID option. Choose the "Registry Format" option and copy and paste the value into the attribute. Make sure you remove the leading '{' and trailing '}' characters from the GUID.

The process for using a .NET object in a COM client is described below.

  1. Establish a strong name for the .NET object so that the CLR knows exactly what assembly the COM component is referring to.
  2. Create a COM callable wrapper (CCW) for the .NET assembly.
    • In order for the COM client to find the .NET object, you must make the Registry entries required by COM. The RegAsm.exe command line utility will generate the required COM type library and make the appropriate Registry entries. If you want to have your .NET object show up as a Windows 2000 Component Service, you can use the RegSvcs.exe utility instead. The RegSvcs.exe utility can generate and register the COM type library and will also install the object into a COM+ application.
    • Another way to make it available is to set the project options in Visual Studio .NET to allow it to register the .NET object as a COM component. Go to the Project menu and select Properties. Select the Configuration Properties. Underneath the Build options, there is a flag for Register for COM Interop. If you set this to true, Visual Studio will perform the RegAsm.exe step for you automatically.
  3. Reference the wrapper assembly in the COM project.

Sample .NET Object

Let's use the scenario where we have an existing COM application. We can't simply rewrite the whole thing at once, so we are going to transition into development with .NET. We found a great and efficient benefit to do our left pad function with .NET that we had previously done in COM. We'll write it in .NET and then utilize it inside our existing COM application.

Here is the class code for our assembly. I generated the GUID in this example by using the steps above within Visual Studiousing System:

namespace COMInteropUtil{  /// <remarks>  /// Utility class to be called by a COM component.  /// </remarks>  [System.Runtime.InteropServices.Guid("6CF0486C-692B-4591-80D5-0C84D6CD5901")]  public class SampleUtil  {    /// <summary>    /// Left pad a string until it reaches a string of the    /// desired length.    /// </summary>    /// <param name="source">Source string</param>    /// <param name="padPhrase">Phrase to pad with</param>    /// <param name="totalWidth">Total length of padded    ///  string</param>    /// <returns></returns>    public string LeftPad(string source,                          string padPhrase,                          int totalWidth)    {  int count     = source.Length;  int lengthPad = padPhrase.Length;  string output = source;  while( count < totalWidth )  {    output = padPhrase + output;    count += lengthPad;  }  return output;    }  }}

Here are the relevant entries from the AssemblyInfo.cs file:

[assembly: AssemblyTitle("CodeGuru COM Interop Sample")][assembly: AssemblyDescription("CodeGuru COM Interop Sample")][assembly: AssemblyKeyFile("..\\..\\key.snk")]

Sample COM Application

In order to test this, I simply created a new standard EXE project in Visual Basic 6.0. I added a reference to the newly registered DLL with the description "CodeGuru COM Interop Sample" as it was dictated in AssemblyInfo.

Private Sub Form_Load()    Dim strTest As String    Dim objInterop As New COMInteropUtil.SampleUtil    strTest = objInterop.LeftPad("test", "pad", 50)    MsgBox strTestEnd Sub

Here is the output from executing the application.

Possible Enhancements

In past columns, we've built some starter objects that you can grow and develop to fit your needs. In this column, we did not build any such objects. As a result, the possible enhancements this time around involve additional COM Interop concepts you can consider exploring.

  • COM and .NET both have their own way of handling errors. COM returns special values from functions to indicate an error condition. .NET handles errors through by throwing and catching exceptions. The wrappers (CCW and RCW) will handle converting the errors to the appropriate style. It is conceivable that this default mapping will not occur as desired and therefore it may be necessary to use a custom wrapper or customize this process in some way.
  • Combining the use of managed and unmanaged threading.
  • Custom marshaling—control how a .NET object is exposed to COM or a COM object is exposed to .NET.

Future Columns

The next column is yet to be determined. It is likely I am going to dive into some of the items in the EnterpriseServices namespace. If you have something in particular that you would like to see explained here, you can reach me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE (NT4/W2K), MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

Page 3 of 3

This article was originally published on February 27, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date