Calling .NET Assemblies with Win32::OLEby InfiniteSilence (Curate)
|on Sep 20, 2004 at 03:15 UTC||Need Help??|
This is a tutorial for calling a .NET assembly via Win32::OLE. I was looking for such a tutorial on the web and previously at PerlMonks but didn't find anything, so I elected to research the issue, get a quick example working, and submit it.
Basically what you want to be able to do is:
Where HelloDot.HelloWorld is a .NET assembly registered in the system to look/act/smell like a regular COM component. The following are preliminary setup steps that do not require explanation:
After mucking with your PATH, you should create a key file like this:
This creates a 'key pair' file which contains a public and a private key for entering the .dll we are about to create into the GAC, the Global Assembly Cache. Think of it as a Windows registry for .NET assemblies. There is a way to separate the public key part from the private one (using sn -p) in case you are interested. (Note: I'm not sure why this thing didn't offer to allow me a choice of ciphers or allow me to choose my own entropy engine. I remember reading that it is using SHA1 or something, but I don't know.)
The first think you will notice when you run an example with the .NET framework is that it is terribly slow. A simple 'Hello World' takes about three seconds to run every time. It seems obvious to me that this thing was not written for quick one-liner-like execution, so be warned. Copy the following hello.cs file and compile it:
You need a constructor with no params for the .NET assembly to be called like a regular COM component (as with Win32::OLE). There is some kind of wrapper that M$soft creates to allow COM components to interact with .NET assemblies and the constructor is necessary to make that happen. If you are interested on the why, more information on that is here. The only problem with this is that a third party .dll is probably not going to have this constructor, so at that point you will have to create a wrapper class that does have it before you try this.
Anyway, you need to compile this into a .dll like so:
If you go back to to the hello.cs code, you will notice the funny lines before the namespace that stand out like a sore thumb: assembly:AssemblyVersion...yadda,yadda. These instructions tell the compiler that you are creating an assembly you are intending to share. If you remove the lines and recompile you will notice that the .dll becomes a little smaller. Remember to put it back in and recompile before you continue this tutorial.
If the .dll compiled okay you now have to register it:
There is one more thing to do. Your .NET assembly still needs to look and act like a regular COM component. Normal COM components (i.e. Excel.Application, Microsoft.XML, etc.) are registered with regsvr32. This puts their GUIDs in the Window's Registry (see HKEY_LOCAL_MACHINE/Software/Classes for the ones you've got). Not so in this case. You need to use regasm.exe in order to 'register' your .NET .dll to be usable by everybody outside of the .NET camp:
With all of this being done, you should be able to call the following:
You may read from various online sources that it is unncessary to load the assembly into the GAC for you to call it as a COM component, but this does not (at least for me) seem to work. Without registering in the GAC I had to copy the .dll to the Windows/System32 directory just to get it to work for the Window's Scripting Host. Win32::OLE simply could not find the bugger until I registered it in the GAC.