When you use an ActiveX control in a .NET applicaton you need to generate run-time callable wrappers (RCW) for the ActiveX object. You can do this manually by using tlbimp.exe and aximp.exe. VS.NET will do this automatically for you if you add a COM object to the toolbox. Behind the scenes VS will do the work that tlbimp and aximp are doing. Generating two assemblies is cumbersome and adds unnecessary clutter to your project., I’m sure most folks would agree.
Using aximp.exe you can actually generate source code by using the /source option and you can include that source within your project to eliminate the AxHost assembly, but that’s all you can do. While this is a bit more compact it’s not a very nice solution.
Tlbimp.exe however does not let you create source which you can compile, you get the assembly output and only the assembly.
You can however combine both RCWs into one component and reference only one dll. In fact, the methods described below will work for almost any COM objects for which you have multiple libs you’d like to combine. You could even go so far as to combine all of your assemblies into one dll….whether or not that’s a good thing could be argued.
Ok, for this experiment we shall use the WebBrowser control (shdocvw.dll).
1. Create a simple winforms application.
2. Add a reference to shdocwv.dll (This should be from the COM tab, you’ll probably have to browse for it: c:\windows\system32\shdocvw.dll on XP).
3. Put the WebBrowser control on your form and in the load event for the form put a call to Navigate() and bring up you’re favorite website: http://blogs.msdn.com/robgruen
4. Compile and run the app and you’ll see everything works fine and dandy.
Now, you’ll see that you have a reference to both AxSHDocVw and SHDocVw. What we are going to do is dump the IL for those assemblies and recompile them into one assembly and then reference that single assembly and everything should work as it did previously.
1. Open a .NET Command prompt and browse to the location of the project we’re working on (the references should be in the bin folder, we might want to copy them to the solution root folder so VS.NET doesn’t delete our work)
2. Run ildasm.exe /out:SHDocVw.il /all /nobar SHDocVw.dll
3. Run ildasm.exe /out AxSHDocVw.il /all /nobar AxSHDocVw.dll
4. Open shdocvw.il in notepad and remove the .assembly directive for SHDocVw.
For me I removed:
.assembly /*20000001*/ SHDocVw
.custom /*0C000003:0A00001C*/ instance void [mscorlib/* 23000001 */]System.Runtime.InteropServices.ImportedFromTypeLibAttribute/* 0100001E */::.ctor(string) /* 0A00001C */ = ( 01 00 07 53 48 44 6F 63 56 77 00 00 ) // …SHDocVw..
.custom /*0C000004:0A000001*/ instance void [mscorlib/* 23000001 */]System.Runtime.InteropServices.GuidAttribute/* 01000002 */::.ctor(string) /* 0A000001 */ = ( 01 00 24 65 61 62 32 32 61 63 30 2D 33 30 63 31 // ..$eab22ac0-30c1
2D 31 31 63 66 2D 61 37 65 62 2D 30 30 30 30 63 // -11cf-a7eb-0000c
30 35 62 61 65 30 62 00 00 ) // 05bae0b..
.hash algorithm 0x00008004
5. Compile the two IL files together to produce a single output. Run ilasm.exe /dll /nologo /quite /out:WebBrowser.dll AxSHDocVw.il SHDocVw.il
6. Open your project again and delete the references to AxSHDocVw and SHDocVw.
7. Add a .NET reference to the WebBrowser.dll file we created with ilasm.
8. Run your project and see that everything works as before but now you have less dependencies.
This cleans up some clutter from your project and if you have multiple ActiveX controls you’re using you can save yourself even more packaging headaches. The IL modification we did above simple removes a duplicate reference as we cannot compile both IL files together without making this modification, you’ll get a duplicate assembly error message.