Search code examples
c#comactivex

How do I call a COM object in C# that I registered using RegistrationServices


I'm experimenting with COM objects and created a simple COM service that acts as a calculator with add, subtract, multiply, divide (details not important).

I then wrote some code to register it dynamically with a C# application

Assembly asm = Assembly.LoadFile("C:\\...COMCalc.dll");
RegistrationServices regAsm = new RegistrationServices();
bool bResult = regAsm.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase);

After registering it I've been able to use the service from an IE browser in javascript.

var num1 = 2
var num2 = 2
var objTest = new ActiveXObject("COMCalc.COMCalc")
alert(num1 + " - " + num2 + " = " + objTest.Subtract(num1,num2))

I'd like to now be able to test it from my C# Application so I can have a register, unregister, and test method for my COM object. I've struggled to find the documentation for how to do this. Any Ideas?

Bonus: I also would like to access it with the GUID defined in the COM object as opposed to the COMCalc.


Solution

  •    regAsm.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase)
    

    By writing your own custom registration method, you are missing out on the normal way that COM client programs or unit testers will exercise your code. They'll use the type library of your COM component, a machine-readable file that describes the types that you expose from your component. It is the COM equivalent of .NET metadata.

    You get a type library by using the normal way to register, either by using your project's "Register for COM Interop" setting or by running Regasm.exe with the /tlb option. Or by running Tlbexp.exe to generate it manually.

    This however does not let you test your component with a C# unit test, you'd normally use Project > Add Reference > Browse and pick the .tlb file. But the IDE refuses to accept it, it can see that the type library was created from a .NET assembly. It insists that you use a normal assembly reference instead, picking the DLL instead.

    There's a very good reason for that. You can fool the IDE by using late binding but that does not fool the CLR. In other words, you are not actually testing the COM interop at all. You might as well use the normal way to add a .NET assembly reference. Truly testing the component requires using a COM client written in a non-.NET language. Not that many practical ones around anymore, you could use a scripting language like Javascript or VBScript. The closer it is to the actual language and runtime environment that is going to use your component, the better. If you are going to use it in a browser then something like Selenium or HtmlAgilityPack would be wise choice.

    Nobody ever likes to hear advice like that. You fool the IDE by late binding, very similar to what you did in the browser:

    Type type = Type.GetTypeFromProgID("COMCalc.COMCalc");
    dynamic obj = Activator.CreateInstance(type);
    dynamic result = obj.Subtract(2, 1);