Register 32-bit COM server (and generate TLB) for

2019-09-19 07:05发布

问题:

Method 1: x86 target platform

I have a .NET class library that is intended for use with both 32-bit and 64-bit clients, some of which are .NET projects and some of which are C++ MFC projects. I can get the library to work with the 32-bit clients, but the 64-bit clients get a "Class not registered" exception. Poking around the registry, it looks like only the win32 key is being set (HKEY_CLASSES_ROOT\Wow6432Node\TypeLib{GUID}\1.0\0\win32).

Some notes on a few of my settings:

  • "Register for COM interop" is checked.
  • "Make assembly COM-Visible" is checked.
  • The "Platform target" is x86.
  • The library contains a 32-bit unmanaged DLL that loads methods with DLLImport.
  • The C++ MFC clients use #import "MyLibrary.tlb" to marshall the interop code.
  • I have not made any changes to the code to support COM. (E.g., I have not overridden System.Configuration.Install.Installer.Install.)

In an effort to resolve this, I have tried several things based on some research and investigation.

Method 2: "Any CPU" target platform

First, I tried setting the Platform target to "Any CPU". In this case, both the win32 and win64 keys are set in the registry, and the 64-bit client can talk to the COM server. However, when I do this, I get the error "An attempt was made to load a program with the incorrect format." This is due to the 32-bit unmanaged DLL, which requires that I build the project with x86.

Method 3: Obtain a 64-bit build of my library's unmanaged DLL dependency

To work around this, I could potentially get a hold of the 64-bit build of the unmanaged DLL. However, we have purchased this DLL from a third party, and for whatever reason, they charge a large, additional fee for the 64-bit build of the DLL. On top of the explicit cost, I would also have to implement DLLImport calls for each and call according to whether it's 32-bit or 64-bit, which would triple the number of methods in my wrapper class. Thus, while this is a possible solution, it's far from desirable, and from what I understand about COM, this shouldn't be necessary.

Method 4: regsvr32.exe

The most common solution I find online for this is to use regsvr32.exe to manually register an application for both 32-bit and 64-bit interop. However, I need the TLB file for interoperability with my MFC clients, and apparently regsvr32 doesn't support this.

Method 5: regasm.exe

To get the TLB file and hopefully register for both 32-bit and 64-bit interop, I have also tried using regasm.exe to register the assembly manually. I used the following command to do this.

"%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm.exe" "D:\Path\To\MyLibrary.dll" /tlb /nologo

However, this registers only the 64-bit COM server and the win32 COM registry key is missing. Now my 32-bit client can't find the COM server and says "Class not registered." Furthermore, for the 64-bit client, I get the same error that I saw when I selected "Any CPU": "An attempt was made to load a program with an incorrect format."


TL;DR How do I register a 32-bit COM server for use with both 32-bit and 64-bit client applications? (Noting that I need the TLB file, and that the server needs to load an unmanaged, 32-bit DLL.)


I think I should clarify the architecture here. Here's a diagram that demonstrates how I want these components to function.

As you can see, I need 64-bit code to interact with 32-bit code by means of a COM server, which, as @MC-ND notes, is supposed to work. How should I configure my COM server to support this?

回答1:

From MSDN: Process Interoperability

On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL). Additionally, a 32-bit process cannot load a 64-bit DLL

Your best option seems to compile your component as a 32bit out of process COM server.