Wednesday, March 28, 2007

Using COM interop services

The past few days have been quite interesting.

Recently I've had a chance to work with XSL and XSLT, the experience was just amazing considering the simplicity and ease of use, i'll probably publish a post on using those later...

The microsoft developers community is slowly migrating towards newer and newer development technologies, but there still a lot of legacy applications out there which require some new development. Here is where COM interop. comes in , it provides the ease of development in .NET while still using the class library as COM in legacy enterprise services such as ASP 3.0

I had a chance to work on a component which was developed in c# .net 2.0 as a class library and called in ASP 3.0

using COM interop is pretty straight forward

when developing a class library for COM interop in .NET its important to keep in mind that
all classes and methods to be accessed from legacy app should be public.

in .net 2.0 and VS 2005 the methods and classes are not visible to COM by default,

one way is to make the whole assembly accessible to COM , goto the project properties, under the application tab click assembly information and check the make com visible checkbox near the bottom



the other method involves using System.Runtime.InteropServices library and declaring [ComVisible(true)] attributes at class and method level for each of the method and class


Registering the Assembly as COM :

after compiling the assembly needs to be registered as COM using the command regasm.exe

a typical example of what I used was something like : regasm /codebase / tlb

the /codebase switch sets the code base in the registry and the /tlb creates a type library and registers it as well

there is another option available in visual studio 2005 in project properties build tab, theres a checkbox option to register for com interoperatibility, but i havnt personally tried using that option.

after registering the component it should be ready for use. I will consider usage from an ASP 3.0 application as an example

from ASP 3.0, the instance can be created by using

Server.CreateObject("namespace.classname") command

note that you have to provide the namespace and class name to create the object, the namespace is not required if creating the component in VB 6, instead you can call the class using the assemblyname.classname insted

after creating the object you should be able to call any of the exposed methods for the class. As for the arguments, I passed and returned the primary data types (including string) from my methods in object


Weird Errors :

Tracing COM errors is a difficult job, I suggest including some built in mechanism for logging events in the class library so it becomes easier to trace if the object breaks.

another problem I faced during development was non-relevant error messages thrown by ASP 3.0 this really gave me a headache. I spent almost the whole day trying to figure it out when calling one of my methods i kept getting an error that the instance was not set for my object.

The weird thing was that if I wrote Response.Write with the object name, it showed that the instance was created by printing the namespace and name of the class. At first I couldnt really understand that if the instance is created, but as soon as i call a method i got the error that the object wasnt set to an instance

Eventually i figured out that this error was caused when my COM object was breaking when i called the method and it gave this weird error about instance not being set.

Permissions :

we had to deploy on win3k server, I faced a number of issues there regarding security

Inn my class library i had to access registry. while testing the classes in .net test application it worked fine but asp 3.0 pages failed to compile giving the error that access was denied to registry keys.

this problem occurs because by default in IIS 6.0 IUSR_ account does not have enough rights to access the registry,
IUSR_is the machine account under which ASP 3.0 apps run

this can be resolved by giving administrative rights to the IUSR account on the machine, but this solution is not feasible for a lot of production environments.

the alternative is to register the .net COM with component services, open the run window type DCOMCNFG in win3k which will open the component services snap-in
follow these steps:
  1. add a new COM+ application
  2. create a blank server application
  3. provide the identity to be used by this com which has enough access rights (such as accessing the registry in my case)
the new COM+ app should have been created now add you component to this application by adding new component, and selecting from the library thats already registered you should see your namespace.classname in the registered components list (you would have to register using regasm.exe before this activity), select the component and add.

I encountered a problem here that one of the classes i created later was not appearing in the registered list. I traced the problem back to visual studio, it seems that even though make COM visible option was selected, the class still wasnt visible.

I had to manually include include the attribute [ComVisible(true)] in the class, recompile it and re-register using regasm (although first you would unregister the previously registered dll using regasm /unregister)

this solved my probem with having not enough access rights to the registry, becuase now i can specify the COM+ application under which identity to run


Win3k Error : could not create object, access denied :

you might get this error while trying to create your com object, to resolve this goto the COM+ application you created in component services, right click and go to the properties window. Under the Security tab there should be an option to enforce security checks/access, uncheck that option



it should now work.


happy COM interoperting!

No comments: