2
votes

I have a 64-bit VB.Net application which needs to use a 3rd party 32-bit unmanaged DLL.

Here are the things I've tried:

  1. I created a 32-bit vb.net wrapper class library, called COM1, and added a VB.Net COM class that calls the 32-bit unmanaged dll's exposed functions. The project had "Register for COM interop" enabled. When I referenced the 32-bit DLL (COM1.dll) to my 64-bit application and executed the application, I received the following exception:

    Could not load file or assembly 'COM1.dll'...An attempt was made to load a program with an incorrect format.

  2. I created a 64-bit vb.net wrapper class library, called COM2, and added a VB.Net COM class that calls the 32-bit unmanaged dll. The project had "Register for COM interop" enabled. When I referenced the 64-bit DLL (COM2.dll) in my 64-bit application and executed the application, I was able to load the 64-bit dll but I received the following exception when I called one of the functions exposed in the unmanaged dll (via the 64-bit wrapper dll):

    An attempt was made to load a program with an incorrect format.

  3. I tried the above steps using a WCF application as well where I replace the COM wrapper with the WCF service, but I get the same result.

I understand that I cannot call a 32-bit dll directly from my 64-bit application. What I am trying to do is call the 32-bit dll through the IPC mechanism — in this case COM or WCF. Obviously, I am making some mistake here.

Can someone give me a working code or tell me what am I doing incorrect in the above-mentioned steps?


Part of my code:

  1. My COM class

    <ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
    Public Class ComClass1
        Public Declare Sub InitializePort Lib "I2CDrvrs" (ByVal I2cAddr As Byte, ByVal evalBoardUsed As Byte)
    
    #Region "COM GUIDs"
        ' These  GUIDs provide the COM identity for this class 
        ' and its COM interfaces. If you change them, existing 
        ' clients will no longer be able to access the class.
        Public Const ClassId As String = "5da6d3a4-848c-42b1-bc7c-4079ec5457b1"
        Public Const InterfaceId As String = "8de9508b-fda6-496e-bb29-a90dc5282d2c"
        Public Const EventsId As String = "cfec40ff-fec0-4250-9d72-9d63f1e37d21"
    #End Region
    
        ' A creatable COM class must have a Public Sub New() 
        ' with no parameters, otherwise, the class will not be 
        ' registered in the COM registry and cannot be created 
        ' via CreateObject.
        Public Sub New()
            MyBase.New()
        End Sub
    End Class
    
  2. My 64-bit application

    Public Function foo() As Boolean
        Try
            COM1.ComClass1.InitializePort(2, 2)
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
        Return True
    End Function
    
2

2 Answers

1
votes

Bringing in a COM DLL as an intermediary (be it 32-bit or 64-bit) doesn't solve the problem. You are still trying to load that 32-bit library into your 64-bit process. No amount of COM trickery will fix that.

The 32-bit library must run from inside a 32-bit process, and communicate with your 64-bit program via [insert your inter-process method of choice here].

You can use COM as an intermediary, sure; that's not a bad idea. But that COM intermediary must be an out-of-process server (an EXE), not a DLL.

A quick way to accomplish that is to install your COM helper as a COM+ (Component Services) application. Compile it as "32-bit", not "AnyCPU". Make sure it's installed as a "Server" not as a "Library". COM+ will provide a 32-bit host process for it.

Whether you can afford the overhead of running a library that was intended to be run in-process through an out-of-process host, I don't know. It will depend on what the library does. In some case, it might simply be impossible (e.g libraries that operate on process-affine resources).

If the DLL must run in-process within your program, then you only have two choices: a) Your program will have to compiled as 32-bit. Or, b) you have to procure a 64-bit version of the library.

0
votes

I have found a rather simple solution to my problem. I implemented a client-server model using Socket Class' methods and properties. I start a 32-bit managed-service code working as the server. The server calls the functions of 32-bit unmanaged dll. So in a way the server acts as a wrapper for the unmanaged dll. I use my 64-bit application as client. I pass a string to the server from my client. The string contains information on the function to be called and its arguments. I parse the string in server and call the appropriate function in the unmanaged dll.