无法从64位托管代码调用32位非托管DLL

时间:2016-11-18 06:39:58

标签: vb.net com ipc

我有一个64位VB.Net应用程序,需要使用第三方32位非托管DLL。

以下是我尝试过的事情:

  1. 我创建了一个名为COM1的32位vb.net包装类库,并添加了一个VB.Net COM类,用于调用32位非托管dll的公开函数。 该项目启用了“注册COM互操作”。 当我将32位DLL(COM1.dll)引用到我的64位应用程序并执行该应用程序时,我收到以下异常:

      

    无法加载文件或程序集“COM1.dll”...试图加载格式不正确的程序。

  2. 我创建了一个名为COM2的64位vb.net包装类库,并添加了一个调用32位非托管dll的VB.Net COM类。 该项目启用了“注册COM互操作”。 当我在我的64位应用程序中引用64位DLL(COM2.dll)并执行应用程序时,我能够加载64位dll,但是当我调用其中一个暴露的函数时,我收到了以下异常unmanaged dll(通过64位包装器dll):

      

    尝试加载格式不正确的程序。

  3. 我使用WCF应用程序尝试了上述步骤,我用WCF服务替换了COM包装器,但是得到了相同的结果。
  4. 据我所知,我不能直接从我的64位应用程序调用32位dll。我想要做的是通过IPC机制调用32位dll - 在这种情况下是COM或WCF。显然,我在这里犯了一些错误。

    有人可以给我一份工作代码,或者告诉我在上述步骤中我做错了什么?

    我的部分代码:

    1. 我的COM课程

      <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. 我的64位应用程序

      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 个答案:

答案 0 :(得分:0)

引入COM DLL作为中介(无论是32位还是64位)并不能解决问题。您仍在尝试将该32位库加载到64位进程中。没有多少COM技巧可以解决这个问题。

32位库必须在32位进程内运行,并通过[在此处插入您选择的进程间方法]与64位程序进行通信。

您可以使用COM作为中介,当然;这不是一个坏主意。但是,COM中介必须是进程外服务器(EXE),而不是DLL。

实现这一目标的一种快速方法是将COM帮助程序安装为COM +(组件服务)应用程序。将其编译为&#34; 32位&#34;,而不是&#34; AnyCPU&#34;。确保将其安装为&#34; Server&#34;不是&#34;图书馆&#34;。 COM +将为它提供32位主机进程。

您是否能够承担运行通过进程外主机在进程中运行的库的开销,我不知道。这取决于图书馆的作用。在某些情况下,它可能根本不可能(例如,在过程仿射资源上运行的库)。

如果DLL必须在程序中运行进程,那么您只有两个选择:a)您的程序必须编译为32位。或者,b)您必须购买64位版本的库。

答案 1 :(得分:0)

我找到了一个相当简单的解决方案来解决我的问题。 我使用Socket Class&#39;实现了一个客户端 - 服务器模型。方法和属性。 我启动一个32位托管服务代码作为服务器。服务器调用32位非托管dll的功能。因此,在某种程度上,服务器充当非托管dll的包装器。 我使用我的64位应用程序作为客户端。 我从客户端传递一个字符串到服务器。 该字符串包含有关要调用的函数及其参数的信息。 我在服务器中解析字符串并在非托管DLL中调用相应的函数。