Welcome!

.NET Authors: Bruce Armstrong, Pat Romanski, Liz McMillan, Yeshim Deniz, Dmitry Sotnikov

Related Topics: .NET

.NET: Article

Do you COM? Dealing with Legacy Projects

".NET 3.0 ... high tech and still unexplored in its entirety"

You might be tempted to say that once you enter the .NET world, you'll never look back. Nothing seems too easy for you at this moment, what with the brand-new .NET 3.0 that's just out, high tech and still unexplored in its entirety.

However, there are situations in which the past catches up, raising the legitimate question of how you can modify your existing .NET projects to allow for interaction with the old Win32 programming model.

Why would a programmer do that? For one, there are those old legacy projects your customers like to use, and nothing can convince them (yet, you hope) to upgrade to the latest and fastest platform out there, thank you very much. Or if you're among those lucky few whose clients are always eager to take the extra step and keep up with the latest technologies, maybe you still have some in-house projects (Visual Basic 6, anyone?) that are too complicated and would take a lot of time and money to convert to your platform of choice.

An elegant solution to these problems is to expose your constructs as Component Object Model (COM) objects that can be used without any problem from any Win32 program that can play with COM. The .NET platform allows you to do just that via a fancy intermediate object called COM Callable Wrapper, or CCW, that sits between the COM client and your managed code. More on this later.

This article will describe what it takes to expose .NET components as COM objects. You'll find that the job is not so difficult; in fact, most of the time what you'll do is play with some new attributes that would decorate your classes, class members, and methods. You'll even learn how to create an ActiveX control in .NET, something that's still hot off Microsoft's hands. But until then, let's start with...

The Basics
The first thing we need for our purposes is, obviously, a normal, not COM-exposed .NET class, which I'll change into a COM-visible component. What's more convenient than a hello-there-like component, like the one shown below:

public class HelloClass {
    public string SayHelloTo(string person) {
       _name = person;
       return "Hello there, " + _name;
    }
    private string _name;
}

Before modifying this class for COM, I need to do a quick detour and explain some of the theories involved in exposing a .NET class to a COM client. The framework component that is of help here is called COM Callable Wrapper (CCW). This is the middleman that stays between your .NET component and the actual consumer. Every call to your class will pass through this proxy, which will take care of the usual COM behaviors for you, like reference counting. When the reference count reaches zero, the .NET object becomes a good candidate for the next round of the framework garbage-collection process.

One more thing about CCW: unlike normal .NET objects, the CCW is allocated from an uncollected heap. This is, in fact, the reason why the wrapper can be used from COM clients in the first place. The CCW object is created on the fly, making everything transparent for you, the .NET class designer.

Coming back to our hello-there class, the first step in the COM-.NET dance is to mark your assembly as being COM visible. For this, you need to go to the AssemblyInfo.cs file for your project (assuming you're writing a C# solution) and change the ComVisible attribute from false (the default) to true, like this:

[assembly: ComVisible(true)]

The effect is that everything that's written in the .NET project will be exposed to the COM world. Well, at least this is the short answer; the real story will get revealed in a moment.

The same thing can be accomplished if you go to your project's properties, select the Application section, and then click on the "Assembly Information" button. The last option in the dialog box that appears is "Make assembly COM-visible," and checking it will take care of changing the ComVisible attribute to true. Still, ComVisible has other interesting uses as well, which you need to understand if you have to master the COM game as seen from a .NET vantage point. What's the point of getting everything for free if you don't get your feet wet, right?

Once you mark an assembly as being COM-visible, everything inside can be accessed by COM clients for free, but this is only partly true. What will actually get exposed is the stuff in the assembly that's public. That's right; all that's private, protected, or internal won't see the COM light, ever. In our hello-there sample, the private data member _name is not exposed at all.

The same is true about all static methods and fields from your constructs. The list of things that won't be accessible includes abstract classes, too. What's more, your public data members will become properties for the new COM object. Did I mention that all types that really need to be exposed should have a default constructor?

The ComVisible attribute, which can be used on every possible level (assembly, class, structure, fields, methods, so on), comes in handy when deciding which public parts of your library will get exposed. When using ComVisible(false) on a public method, for example, it won't be visible from COM clients. However, you can still use it from other .NET applications.

Now that you know how to play nice with COM, all that remains to be done is to... yes, you guessed it - register the resulting assembly in the Windows Registry, so that other applications know about it and use it. The next stop will be...

The Registration Story: The .NET Way
Normally, a COM library must be added to the Windows Registry using the RegSvr32.exe utility. Not so for .NET components. Remember, RegSvr32.exe is used to register/unregister native Win32 DLLs and ActiveX controls, and won't work on the resulting .NET library.

Enter the RegAsm.exe command line tool - or the Assembly Registration Tool. This small application will take a .NET component, read its metadata, determine what constructs (classes, structures, so on) are marked as COM-visible, and write the necessary entries in the registry. This friendly tool is smart enough to do a little bit more than that, such as generating a type library for the exposed component, or creating a registry script containing the registration details. Neat, isn't it?

You might want to play with the tool to see what other options are available.

Assuming that our hello component compiles to a Hello.dll library, here's how you can register it:

RegAsm.exe Hello.dll


More Stories By Catalin Sandu

Catalin Sandu is a software developer at RomSoft (www.rms.ro) and has 10 years of experience. He is both a Microsoft Certified Professional (on C++ and .NET), and an Advanced ColdFusion MX 7 Developer. Catalin is also a member of the British Computer Society since 2005.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.