OK while I never thought in 2012 I would be writing my first ActiveX control (and yes there is a good reason for it) I am struggling with getting it running under Windows 7 (x64).
The Solution Short Story: I was missing /codebase from some of my regasm calls and also mixing up 32 and 64 bit processes, but that wasn't being helped by the standard VS2010 command prompt mixing up 32 and 64 bit paths for regasm and cscript.
The long story follows:
I have been bouncing between
Creating an ActiveX control in .Net using C#
(Oops I had the wrong link .. although it looks like the link I initially supplied was someone copying the original blog page)
Creating an ActiveX control in .Net using C#
and
C# ActiveX control (CSActiveX)
And I appear to be building the projects successfully (for the latter one I had to change the resource compiler location to the correct location).
For the first project I am using the suggested installer, for the second project I am trying to use regasm directly.
But after this it all goes down hill. I try and register the all's but either:
I have no idea how I should be registering them, or:
I have no idea how I should be registering them.
My test case has been a simple JScript file containing
var x = new ActiveXObject( "name of object" );
Which fails with the error:
test.js(1,1) Microsoft JScript runtime error: Automation Server can't create object
I am not sure if this is a permissions issue, or a 32 vs 64 bit issue or a combination.
A lot of sites offering help on ActiveX are assuming you will be accessing it via a web page , so I have tried looking at IE permissions (even though I want to load the control into a 3rd part program).
I know if I use either the 'framework' or 'framework64' versions of regasm I can control where in the registry entries get put - and I have seen some references to running cscript as either 32 or 64 bit (which possible affects what part of the registry is searched) depending on the cmd shell invoked (and I have tried both ways, as well as trying an "administrator" shell).
So basically at this point I have no idea what I am doing or what I should be doing.
My goal is to register an ActiveX control on Windows 7 x64 and have it be able to be loaded by:
A test .js script running from the default Windows command prompt
Load the same control into something like Excel 2007 VBA (for testing only)
Load the control into a 3rd part application (RSView Studio from Rockwell) and have it hosted within a VBA application (and I need to check if this isa 32 or 64bit program .. I suspect the former)
Notes
For the project that users the installer (Creating an ActiveX control in .Net using C#), it installs the code into "c:\program Files (x86)\" and looking with regedit I find entries under "Computer\HKEY_CLASSES_ROOT\Wow6432Node\CLSID\" which I believe is telling me that the DLL was installed as a 32 bit process. I have tried running my cscript test from both a 32 and 64 bit cmd and they both fail. NOTE that the installer was creating the equivalent of "regasm /codebase" when it ran.
For the project where I tried using regasm to register it (C# ActiveX control (CSActiveX)), it has some additional code for registering an ActiveX COM control. This code mentions registering 32 bit in-process servers (see ActiveXCtrlHelpers.cs)
(BTW I'm also cursing auto correct in Safari/Lion at the moment, keeps changing lower case "DLL" into "all")
Edit 2012-08-07
Prompted by Art's answer I discovered:
From standard VS2010 command prompt
When running 'regasm /codebase' through the standard VS2010 command prompt (and as administrator to allow regasm to perform changes), the entries got dumped into the registry under HKEY_CLASSES_ROOT\Wow6432Node\CLSID and the test scripts failed from the same prompt.
However I can see the ActiveX control in Excel 2007 (32 bit)
From x64 Win64 VS2010 command prompt
When running under the VS2010 x64 Win64 command prompt (again as admin) the registry entries appeared under HKEY_CLASSES_ROOT\CLSID but this time the test scripts worked from the same prompt and also from a standard Windows cmd prompt (however they fail from a 32 bit prompt)
But!! I can't see the active X control from Excel 2007 (32 bit)
Now I just need to figure out what the windows equivalent of the *nix 'which' command to ensure which regasm I am using) the 'where' command
Looking at the VS2010 and Windows 7 command prompts:
VS2010 (standard prompt): cscript => c:\windows\system32\cscript.exe
regasm => c:\windows\Microsoft.net\framework\v4.0.30319\regasm.exe
VS2010 (x64 Win 64): cscript => c:\windows\system32\cscript
regasm => c:\windows\Microsoft.net\framework64\v4.0.30319\regasm.exe
Windows 7 std. prompt: cscript => c:\windows\system32\cscript.exe
Windows 7 32 bit prompt: cscript => c:\windows\SysWOW64\cscript.exe
This is all starting to make some of my confusion understandable. I have been unknowingly mixing and matching 32 and 64 bit systems, but the VS2010 standard prompt didn't help either!
(and my latest peeve - VS2010 saving files as UTF-8 with BOM)
I was able to make this work both via IE and vbscript by doing the following:
Create .NET class library named 'ActiveXTest'
Add a class named MyObject which is defined as follows:
namespace ActiveXTest
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ProgId("ActiveXTest.MyObject")]
[System.Runtime.InteropServices.Guid("df2dac4d-ba8a-4ecc-b76e-958c1bc32f1f")]
public class MyObject
{
public string HelloWorld()
{
return "This is Hello World from the COM component!";
}
}
}
Compile the class. Go to the folder where you compiled the class and do the following from a Visual Studio command prompt: regasm /codebase ActiveXTest.dll
To test from a .vbs script, create a file in notepad call test.vbs. type the following into the file:
Dim myObject
set myObject = CreateObject("ActiveXTest.MyObject")
MsgBox(myObject.HelloWorld)
Open a command prompt and navigate to where where you created the Test.vbs and type: wscript test.vbs. A dialog should be displayed stating "This is Hellow World from the COM component"
To test this from IE, I created a TEST.HTML file with the following contents:
<HTML>
<HEAD>
<script language="JScript" language="JavaScript">
var obj = new ActiveXObject("ActiveXTest.MyObject");
alert(obj.HelloWorld());
</script>
</HEAD>
<body>
<span>nothing to see here!</span>
<body>
</HTML>
Open the TEST.HTML file in IE. You will get a warning about the ActiveX control; just say Yes to allow the interaction. You will get an alert dialog stating "This is Hello World from the COM Component".
Similar steps can be used to make it work from a .js file or from Excel VBA. Note that if you change the COM method signature of the ActiveX assembly I believe you will need to re-register it.
Related
There are a few questions (and unwanted answers) all over the forums about Microsoft.ACE.OLEDB.12.0 provider not being registered on the local machine, like this one. The gist of the problem, how I understand it, is that the application will look for the provider on the same platform as what the application is running on. So if your computer is 64 bit and the provider 32 bit, then there will be a mismatch if you don't compile the application to run in 32 bit mode.
Most answers effectively deal with this by installing the appropriate data components for the current platform. Other suggestions are to compile for whichever platform the data components are available.
I am developing an app using PCs running Windows 7, 8 and 10, all 64 bit, depending on where I am, but some have older versions of Office and others newer versions. This causes me to have to change the platform for which I compile depending on the PC I currently work on. While this is no problem for me, personally, I foresee this causing headaches for the end users not being able to run the program.
Trying to avoid asking users to install other components on their computers; is there a way I can tell the program to check the platform availability of the database provider and then run in that mode? Might it be possible to create 32 bit and 64 bit extensions of the database module and load the appropriate one regardless of the mode the main program is running in?
EDIT:
I just tried to compile my database extensions on different platforms Whichever one that is not the same platform as the application causes an exception when being loaded saying that I am attempting to load an assembly from a different platform. So I guess I'm out of luck with my option 2...
You can use CorFlags utility to modify your executable on target machine, after you will detect which mode it needs to run.
First ensure that your main exe is compiled under any cpu with Prefer 32 bit flag not set. Now when application is started you need to check if we are in 64-bit process or not, and also check your dependencies (this I won't cover - I don't work with OLEDB). If you found mismatch (say you are running in 64-bit process but your dependencies are 32-bit) - you need to run external process to modify your main executable and then restart it. Easiest way to do it is via simple cmd script, like this (in this example my main exe is called ConsoleApplication3.exe):
:start
start /wait "" "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\CorFlags.exe" ConsoleApplication3.exe /32BIT+
if errorlevel 1 (
goto start
)
start "" ConsoleApplication3.exe
Note that this is just example and if something goes wrong it will fall into endless loop, adjust to your requirements. What this script does is just updates your exe using CorFlags tool to run in 32-bit mode, then starts your main exe.
Right after starting your application, you might do the following check:
static void Main() {
if (Environment.Is64BitProcess) {
// here you also check if you have dependency mismatch, and then:
Console.WriteLine("Running in 64-bit mode. Press any key to fix");
Console.ReadKey();
// run script (here we assume script is in the same directory as main executable, and is called fix-mode.cmd
var process = new Process() {
StartInfo = new ProcessStartInfo("cmd.exe", "/c call fix-mode.cmd")
};
process.Start();
// here you should exit your application immediatly, so that CorFlags can update it (since it cannot do that while it is running)
}
else {
// after restart by our script - we will get here
Console.WriteLine("Running in 32bit mode");
}
}
Note that this tool (CorFlags) is available only with Visual Studio so you may want to pack it together with your application (might be not available on remote machine).
I have a C# COM object in a dll that I have registered using regasm.exe.
I do a createObject on the COM object and call methods on the object in a vbs script run with cscript.
If I run this on the command line it all works properly, creates the object calls the method via com.
cscript.exe c:\mypath\myvb.vbs argument
I now am trying to run this same command from C#. I use the System.Diagnostics.Process methods
ProcessStartInfo si = new ProcessStartInfo();
si.Filename = "cscript.exe";
si.Arguments = "c:\mypath\myvb.vbs argument";
Process exe = ProcessStart(si);
...
When I run this way I get the 0x80070002 error , which is basically a file not found error. I dont understand why it is different from C# to the command line.
Edit - More Info
I am running on a 64bit OS. The C# COM dll was built with "AnyCPU" .
I used the 64bit regasm.
The cscript I used was from c:\windows\system32 so it was the 64 bit version.
From the command line if I deliberately use the 32 bit version of cscript I also get the 0x80070002 error. This leads me to suspect the problem from c# is related, but I still don't get it.
"File not found" is not the first kind of error you'd expect in this scenario. But it is certainly possible, you have to register the assembly twice. Once with the 64-bit version of Regasm.exe so that the 64-bit registry keys are written. And again with the 32-bit version, it writes the keys to HKLM\Software\Wow6432Node, where 32-bit client programs search for keys.
Which is easy to overlook of course, you never mentioned doing this so that's a Big Red flag. You'd normally get "Class not registered", that didn't happen, maybe there was an earlier registration we don't know about. Like Visual Studio registering it, you'd normally always favor it doing that way because it prevents registry pollution. Simple changes to the project or file can then trigger "File not found". Forgetting the /codebase option when you ran the 32-bit version of Regasm is another way.
Best thing to do is just not guess at this. File not found errors are very easy to diagose with SysInternals' Process Monitor. You'll see cscript.exe searching for the file and not finding it. The name of the file gives you a very strong hint what the underlying cause can be. Look at the trace from the bottom up to avoid drowning in the data. And pre-emptively ensure you use both versions of Regasm.exe because you know that's necessary.
By gleaning bits of information from various posts, I have come so far, but still not there yet.
I am trying to create a dll in C# which can then be used by php.
I have created a VS2012 C# class library project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace test1
{
[System.Runtime.InteropServices.Guid("0283F337-AF8D-45BE-BD32-829F5976E9EF")]
[ComVisible(true)]
public class Class1
{
public Class1()
{
// do nothing
}
public int blah()
{
return 42;
}
}
}
Platform Target: Any CPU
Target framework: .NET Framework 4
I have compiled this and have got a test1.dll file.
I have tried registering it with:
regsvr32 test1.dll
but get the following error:
The module "test1.dll" was loaded but the entry-point DllRegisterServer was not found.
Also tried:
regsvr32 /i /n test1.dll
but I get this error:
The module "test1.dll" was loaded but the entry-point DllInstall was not found.
I use:
regasm test1.dll
and that says it is successful.
I next create a test php file:
<?php
$obj = new COM("test1.Class1");
$output=$obj->blah();
echo $output;
?>
I also add the following to my php.ini:
[PHP_COM_DOTNET]
extension=php_com_dotnet.dll
but when I run it, I get:
Fatal error: Uncaught exception 'com_exception' with message
'Failed to create COM object `test1.Class1': Class not registered
So it seems to me that I have to use regsvr32 and make some changes in C# to deal with the DllRegisterServer issue
Can somebody fill me in on what else I need to do to make this work.
I am using:
PHP 5.6.7
Visual Studio Express 2012
Windows 8.1 (64 bit version)
Addendum:
Also tried:
regasm test1.dll /tlb:test1.tlb
regsvr32 test1.tlb
That gives me:
The module "test1.tlb" may not be compatible with the version of Windows
that you're running. Check if the module is compatible with an x86 (32-bit)
or x64 (64-bit) version of regsvr32.exe.
I get that message whether the platform target is "x64" or "any CPU".
test1.dll is not really a COM dll, you can't register it.
You need to follow the steps(https://msdn.microsoft.com/en-us/library/x66s8zcd.aspx) to enable COM.
To set up the code in your class to create a COM object
In Solution Explorer, double-click Class1.vb to display its code.
Rename the class to ComClass1.
Add the following constants to ComClass1. They will store the Globally Unique Identifier (GUID) constants that the COM objects are required to have.
VB.NET
Public Const ClassId As String = ""
Public Const InterfaceId As String = ""
Public Const EventsId As String = ""
On the Tools menu, click Create Guid. In the Create GUID dialog box, click Registry Format and then click Copy. Click Exit.
Replace the empty string for the ClassId with the GUID, removing the leading and trailing braces. For example, if the GUID provided by Guidgen is "{2C8B0AEE-02C9-486e-B809-C780A11530FE}" then your code should appear as follows.
VB.NET
Public Const ClassId As String = "2C8B0AEE-02C9-486e-B809-C780A11530FE"
Repeat the previous steps for the InterfaceId and EventsId constants, as in the following example.
VB.NET
Public Const InterfaceId As String = "3D8B5BA4-FB8C-5ff8-8468-11BF6BD5CF91"
Public Const EventsId As String = "2B691787-6ED7-401e-90A4-B3B9C0360E31"
Make sure that the GUIDs are new and unique; otherwise, your COM component could conflict with other COM components.
Add the ComClass attribute to ComClass1, specifying the GUIDs for the Class ID, Interface ID, and Events ID as in the following example:
VB.NET
<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
Public Class ComClass1
COM classes must have a parameterless Public Sub New() constructor, or the class will not register correctly. Add a parameterless constructor to the class:
VB.NET
Public Sub New()
MyBase.New()
End Sub
Add properties, methods, and events to the class, ending it with an End Class statement. Select Build Solution from the Build menu.
Now, you can register your dlls using regsvr32.
It's not really an answer, but is a bit of a work round. It looks like the 64 bit version does not work in windows 8.1 or in VS2012 Express or the combination of both even though it is the 64 bit version of the OS.
If I build the solution with a platform target of x86, it all works fine.
I have also discovered that there are two regsvr32.exe files on windows 8.1, one in c:\windows\system32 and one in c:\windows\SysWoW64. I've had no success with either of them.
The first is for registering 64 bit versions of Dlls and the second for 32 bit versions.
Fortunately for me, I don't need to have a 64 bit version.
That all said, I can only register it in VS, so I still have to figure out how to register it on the actual server.
Addendum
Got a step closer today - can now register it on my development PC at the cmd prompt
Steps involved:
Run VS2012 express as administrator
I removed the [System.Runtime.InteropServices.Guid... line as it seems that it is not needed
I signed the assembly:
right click project name in solution explorer and select properties
Select "Signing"
Tick "Sign the assembly"
Choose "New..." under "Choose a strong name key file"
I gave mine a name of test1.snk and chose not to password protect it
Build it (F7)
At the cmd prompt (run as administrator):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe test1.dll /tlb:test1.tlb /codebase
This now works on my Windows 8.1 PC
I copy this over to the Win 2008 R2 server and try the same:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe test1.dll /tlb:test1.tlb /codebase
but I get a popup window with this error:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe is not a valid Win32 application
followed by a "Access is denied." at the cmd prompt.
I have discovered that there are 12 different versions of regasm.exe installed on Win8.1 and 10 on Win2008R2. I have tried them all, but the one that works is the one I have been using all along.
In case it's of use to anyone, here they are:
WIN 2008 R2
C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe
C:\Windows\winsxs\amd64_regasm_b03f5f7f11d50a3a_6.1.7601.17514_none_a3c349b4bdac0898\RegAsm.exe
C:\Windows\winsxs\amd64_regasm_b03f5f7f11d50a3a_6.1.7601.18523_none_a3c462acbdab0575\RegAsm.exe
C:\Windows\winsxs\amd64_regasm_b03f5f7f11d50a3a_6.1.7601.22733_none_8cf7bc12d7517f23\RegAsm.exe
C:\Windows\winsxs\x86_regasm_b03f5f7f11d50a3a_6.1.7601.17514_none_eb70808bd228319e\RegAsm.exe
C:\Windows\winsxs\x86_regasm_b03f5f7f11d50a3a_6.1.7601.18523_none_eb719983d2272e7b\RegAsm.exe
C:\Windows\winsxs\x86_regasm_b03f5f7f11d50a3a_6.1.7601.22733_none_d4a4f2e9ebcda829\RegAsm.exe
WIN 8.1
C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe
C:\Windows\WinSxS\amd64_regasm_b03f5f7f11d50a3a_4.0.9600.16384_none_95117f30a7195a76\RegAsm.exe
C:\Windows\WinSxS\amd64_regasm_b03f5f7f11d50a3a_6.3.9600.16384_none_ea742672c514173d\RegAsm.exe
C:\Windows\WinSxS\amd64_regasm_b03f5f7f11d50a3a_6.3.9600.17226_none_ea6df930c519af4b\RegAsm.exe
C:\Windows\WinSxS\amd64_regasm_b03f5f7f11d50a3a_6.3.9600.20708_none_d39e21d6dec31402\RegAsm.exe
C:\Windows\WinSxS\x86_regasm_b03f5f7f11d50a3a_4.0.9600.16384_none_dcbeb607bb95837c\RegAsm.exe
C:\Windows\WinSxS\x86_regasm_b03f5f7f11d50a3a_6.3.9600.16384_none_32215d49d9904043\RegAsm.exe
C:\Windows\WinSxS\x86_regasm_b03f5f7f11d50a3a_6.3.9600.17226_none_321b3007d995d851\RegAsm.exe
C:\Windows\WinSxS\x86_regasm_b03f5f7f11d50a3a_6.3.9600.20708_none_1b4b58adf33f3d08\RegAsm.exe
So I'm a step closer, but still not quite there. Still can't compile a 64 bit version (don't need it, but was hoping I could get that version to work on WIN2008R2) and can't register the 32 bit version (x86) on the server.
Addendum2
Success - finally. I noticed that C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe had a size of zero bytes (goodness knows why), so I copied one from another win2008r2 server and all is well. So I'm a happy man - don't care about the 64 bit version :-)
I have successfully got Reg-Free COM working using C++ and C# using manifest files i.e. early binding. I am now trying to get this working using late binding. The technique I have found, after much web searching, appears to be using "Microsoft.Windows.ActCtx".
An example I used to test this was MS's "Registration-Free Activation of COM-Based Components" found at http://msdn.microsoft.com/en-us/library/ms973913.aspx to generate the SideBySide example. I then attempted to use a scripting language; VBScript and Python however both have fail in the same way (also tried VBA). The VBScript example is given below:
Set actctx = CreateObject("Microsoft.Windows.ActCtx")
actctx.manifest = "C:\test\client.exe.manifest"
Set SBSObj = actctx.CreateObject("SideBySide.SideBySideClass")
wscript.echo SBSObj.Version
Using something like SysInternals' "Process Monitor" you can see that running the following command (Windows 7 x64):
C:\Windows\SysWOW64\cscript.exe //Nologo C:\test\VBRegFreeTest.vbs
appears to work by loading the manifests and attempt to start looking for the equivalent registry calls and fails to find them. So it appears to partially work. I've also copied wScript.exe to the local directory to rule out directory issues for running application and manifest files.
I've read Microsoft.Windows.ActCtx on Windows Xp and have included the "prodID" in the manifest but it still fails. The manifest files work correctly with C++ and C# examples.
I can't help feeling that the "Microsoft.Windows.ActCtx" has issues. Documentation on this is very limited. Any help on using manifest files with Python or VBScript would be very much appreciated. I would be interested to know if anyone has got "Microsoft.Windows.ActCtx" to work.
Your EXE must have manifest with dependency section describing name and version of COM server, e.g. SideBySide.dll.
If your EXE has internal manifest: Windows 7 will not read external manifest, if internal one exists (Windows XP looks firstly for external manifest).
On Windows 7 the internal manifest of EXE must be changed with dependency to COM server, or internal manifest must be removed from EXE. It is possible with mt.exe from Visual Studio.
SideBySide.dll and SideBySide.dll.manifest must be in the same folder as EXE.
SideBySide.dll.manifest must include progID of COM server in comClass section.
Example of VBS code, using DLL from: Registration-Free Activation of COM Components: A Walkthrough
Dim o
Set o = CreateObject("Microsoft.Windows.ActCtx")
//in example here is a manifest reference: o.manifest = "SideBySide.X.manifest"
//but it does not function by me. By me a dependency is described in manifest of EXE.
Dim obj
Set obj = o.CreateObject("SideBySideLib")
Call MsgBox(obj.Version())
Set obj = Nothing
Set o = Nothing
We've created a C# class library assembly and made it COM visible to be able to call its methods from PHP. This used to work fine, but now we wanted to install it on a Windows Server 2008 server and we keep walking into the error "Class not registered".
To rule out any dependency problems I made a tiny little test class library in C#. The class library is built for Any CPU and it is COM visible (also set COMVisible to true in AssemblyInfo.cs). The test class library only contains one class with one method. The class is called TestLib and the namespace is also called TestLib. The method is called Test and only returns a string.
What we have done is the following:
- built the TestLib.dll
- copied it to the Windows Server 2008 machine
- registered the dll with: regasm /codebase TestLib.dll
- the regasm tool returns a success message
- in PHP we simply try to create a new COM instance:
try
{
$test = new COM("TestLib.TestLib");
}
catch (Exception $e)
{
die($e->getMessage());
}
when we call this test script from either the browser or the commandline (php -f test.php) we get the error "Class not registered" in both cases
I also tried adding TestLib to the GAC by using gacutil -i, but to no avail; still the class not registered error.
Then I tried compiling the testlibrary with .NET 2.0 instead of 4.0 as the target framework, same result. The .NET framework 4.0 is installed on the server by the way.
Any ideas?
Okay, so after some more research I figured it out. The php.exe process is 32 bit. The COM visible assembly is compiled for Any CPU so it should be accessible to both 32 and 64 bit applications.
The problem is that on a 64 bit OS php.exe, and any 32 bit process for that matter, searches in HKEY_CLASSES_ROOT\Wow6432Node\CLSID instead of HKEY_CLASSES_ROOT\CLSID and in HKEY_LOCAL_MACHINE\Software\Classes\Wow6432Node\CLSID instead of HKEY_LOCAL_MACHINE\Software\Classes\CLSID. The registry entries in the Wow6432 keys aren't created by regasm that is shipped with .NET framework v4 on Windows Server 2008. On Windows 7 they are created, don't ask me why.
It also turned out that if I create a little test assembly for .NET v2.0 and register it with regasm that ships with .NET framework v2.0 that it does create the Wow6432Node entries on Windows 2008. Strange.
So my solution is to create a basic registry file on the server using:
regasm /regfile MyClassLib.dll
This creates a file MyClassLib.reg with only the 'normal' 64 bit entries. Then I exported the Wow6432Node keys from a Windows 7 machine and added it to that .reg file. Now when I import that reg file into the registry on Windows 2008 everything works fine.
For more info on the Wow6432Node entries check out: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072%28v=vs.85%29.aspx
Hope this saves someone else some time and headaches.
If you are trying to call a 32-bit COM DLL on 64-bit Windows, you will need to register it.
Copy your 32-bit DLL to C:\Windows\sysWOW64
Run C:\Windows\sysWOW64\regsvr32.exe your_com_32.dll
A bit more info with screenshots.