My Technical Notes

Tuesday, 19 May 2015

Creating a COM Component in C#

Here are the steps to expose a library written in C# to COM:

Setting COM-Visibility

Set the `ComVisible` attribute to `true` in `AssemblyInfo.cs`:


[assembly: ComVisible(true)]
This will make all public classes visible to COM. If you want to selectively hide a class, then put

[ComVisible(false)]
on top of it.

Registering the Library

You can register your .NET library with COM in two different ways:

1. Using Visual Studio, go to the project properties, go to the `Build` tab, and check `Register for COM interop`. COM interop registration will happen on each build.

2. For more control, use the `regasm.exe` command line utility.

There are two versions of `regasm.exe`, the 64-bit version resides in `Framework64`. Full path:


c:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe
The 32-bit version resides in the `Framework` folder (remove "64" from the above path):

c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe
Use the appropriate version, depending on whether you want to register it for a 64-bit consumer or a 32-bit consumer.

Execute the below command:


regasm <dll name>.dll /tlb /codebase

With the `/codebase` parameter, it is recommended to strong-name the assembly.

To unregister the interface, we do:

regasm /unregister .\<dll name>.dll /tlb:<dll name>.tlb

C# class

Note that all attributes mentioned below are found in `System.Runtime.InteropServices` namespace.

Because all types in the DLL will be visible to COM, it suffices to add only one attribute on top of a class we wish to expose:


[ClassInterface(ClassInterfaceType.AutoDual)]

For example:


[ClassInterface(ClassInterfaceType.AutoDual)]
public class Arithmetic
{
    public int Add(int x, int y)  
    {
        return x + y;   
    }
}

This will generate an interface based on the class.

If, instead we wish to follow the guidelines and create a separate interface for each COM class, as like [1] explains and [2] recomments, we must generate GUIDs for each class (using Tools → Create GUID) and set other COM specific attributes:


[Guid("5715C11C-55E8-45B4-9372-FD0FD9AA6F7C")]
public interface IArithmetic
{
    int Add(int x, int y);
}


[
    Guid("92D467E4-F6B7-4B88-8B87-00CF78794852"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(IArithmetic))
]
public class Arithmetic : IArithmetic
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

I had to do this to expose it to an AutoHotKey script, otherwise it would not find the method.

Testing the COM component in PowerShell

Assuming that the library name is `ClassLibrary1`, the following PowerShell code should successfully instantiate an `Arithmetic` object and use it to add two numbers together.


$wx = New-Object -ComObject ClassLibrary1.Arithmetic
$result = $wx.Add(9, 15) 
# $result == 24

No comments: