30 September 2012

Creating RCW Interops from ActiveX (OCX) Controls

Many times we need to use ActiveX controls (ocx) developed in VB6 or C++ in our .NET applications. As you might aware of that, we can't directly use ActiveX components in .NET application. So, we need to create wrapper assemblies around the ActiveX components which we call Runtime Callable Wrappers as I have already talked about that in my previous posts. I am not going to discuss details of RCW, but I will show how to generate the RCWs.
You can generate RCW in two ways
1. Using Visual Studio
2. Using Tools TlbImp.exe and AxImp.exe.

Using Visual Studio to generate RCW:
This is the simplest way of generating RCWs. Then in your project, open the toolbar, right click on it and select 'Choose controls'. Browse the .ocx file and click OK.
Now open the 'obj' folder present inside the project folder and you will see two interop dlls are generated namely AxInterop.<FileName>.dll and <FileName>.dll. For example, if the control name is MyControl.OCX then generated assemblies will be AxMyControls.dll and MyControls.dll. The prior one contains the visible components of the user control that can be placed on the form. And later one contains the types.
Using Tools to generate RCW:
Above method of generating RCW fulfils most of the times. However, if you want to have some control over how the interops are generated like default namespace, strong naming etc., you can't do much with Visual Studio. However, for that you can use framework tools to generate RCW yourself.
AxImp.exe and TlbImp.exe are two such tools that ship with NET Framework SDK. In fact AxImp.exe alone is sufficient to generate required interops. We will how that works now. Suppose you have an ActiveX control called MyControl.OCX. Open the visual studio command prompt, change the directory to the folder where MyControl.ocx resides and run the below command.
This will generate two interops AxMyControl.dll and MyControl.dll. The default namespace in the prior one will be AxMyControl and default namespace in MyControl.dll will be MyControl. If you want to change the out putfile name to AxInterop.MyControl.dll, you can run the below command,

AXIMP MyControl.OCX /OUT:AxInterop.MyControl.dll
This will generate AxInterop.MyControl.dll and MyControl.dll. You can see that when using AXIMP tool, you do not have any control over other interop dll i.e. MyControl.dll. You also do not have control over default namespace name. So, if I want to give your own names say AxInterop.MyControl.dll and Interop.MyControl.dll with custom namespaces say LegacyControls, then I will do it as below:
First generate the interop assembly containign type definitions using TLBIMP tool as below,

 TLBIMP MyControl.OCX /OUT:Interop.MyControl.dll /namespace:LegacyControls
If you want the generated assembly to be strong named, you can supply the strong name key file to above command (as below)

TLBIMP MyControl.OCX ... /KEYFILE:MyCompanyKey.snk
Now generate the ActiveX interop using AXIMP tool using the above generated RCW,

AXIMP MyControl.OCX /OUT:AxInterop.MyControl.dll /RCW:Interop.MyControl.dll
and of course you can sign this assembly just like as explained before.
Now you have generated the two interops AxInterop.MyControl.dll and Interop.MyControl.dll with having namespace AxLegacyControls and LegacyControls respectively.
Note: You must register the OCX before you can use the generated interops.