在 64 位 .Net 应用程序中导入 32 位 dll

Posted

技术标签:

【中文标题】在 64 位 .Net 应用程序中导入 32 位 dll【英文标题】:32 bit dll importing in 64 bit .Net application 【发布时间】:2011-03-03 11:49:20 【问题描述】:

我遇到了问题,从昨天开始我一直在尝试解决它,但没有成功。 我有一个 32 位 Delphi DLL,我想将它导入到 .NET WIN 应用程序中。此应用程序必须在 ANY CPU 模式下构建。当然,会抛出异常 BadImageFormatException,这意味着 64 位应用程序无法加载 x86 DLL。 我四处搜索并找到了一个解决方案,它说我必须做包装,但对我来说并不清楚。谁能告诉我如何解决这个问题,有什么方法可以将 32 位 Delphi DLL 导入到任何 CPU 架构(64 位、32 位)或其他解决方案下构建的程序中?

【问题讨论】:

为什么不将 .NET 应用程序编译为 x86? 为什么它必须被编译为任何 CPU? 32 位应用程序将在 64 位操作系统上运行。 @OregonGhost 因为现在是 21 世纪。 @sproketboy:21 世纪的现实是,您无法在 64 位应用程序中加载 32 位 DLL,并且无论何时需要这样的 DLL(这几乎总是我工作的地方) ,由于硬件访问或通信要求),您无法编译为 64 位。在几乎所有情况下,您实际上并不需要 64 位。我不认为“现在是 21 世纪”是一个很好的理由;) @OregonGhost 我们的 Java 应用程序可以充分利用 64 位,甚至无需重新编译任何东西。 【参考方案1】:

您需要做的是在 32 位进程中编写一个承载 32 位 DLL 文件的包装应用程序。

然后,您的 64 位应用程序必须与这个 32 位进程通信,通过网络方式,或通过 COM 对象或类似方法使 DLL 函数可用。

无法在 64 位进程中运行 32 位 DLL,无论您如何努力,都需要在 32 位进程中运行它。

如果不能只为 32 位编译您的应用程序,您别无选择,只能创建一个主机应用程序。

【讨论】:

你能给我任何来源吗?我该怎么做?或者你知道哪里可以有详细的解释吗?非常感谢 我很确定 64 位应用程序也不能使用 32 位 COM 组件,还是我错了?我在使用 32 位 COM 控件之前遇到过这个问题,并且在我将 C# 项目编译为 X86 之前遇到了错误。 不幸的是,这不是我的选择:( 我认为他们可以使用进程外 COM 对象,但我实际上并不知道。 @scatterbraiin,“什么”不适合你? @Lasse V. Karlsen 将我的 C# 项目编译为 X86【参考方案2】:

一般的想法是用托管的 32 位包装 dll 包装您的(非托管)32 位 DLL 并使其 COM 可见。这允许通过其 COM 接口调用您的包装 DLL。

您可以使用 COM 代理使您的 COM dll 显示为进程外 COM 服务器。 请查看这个 SO 问题以获取有关此主题的更多信息:Access x86 COM from x64 .NET。

【讨论】:

【参考方案3】:

据我了解,您无法在 64 位应用程序中使用 32 位 DLL。也就是说,您只能为 X86 编译您的应用程序。

您找到的解决方案可能是关于如何在“任何 CPU”编译的项目中使用 32 位和 64 位版本的 DLL,具体取决于应用程序是在 32 位还是 64 位中运行环境。

为此,您可以在 C# 中编写两个包装 DLL,一个用于 64 位,一个用于 32 位,并根据您是在 64 位还是 32 位操作系统上运行而使用各自的包装器。

但是,当您只有一个 32 位 DLL 时,这不起作用。 64 位应用程序不能使用 32 位 DLL,32 位应用程序也不能使用 64 位 DLL。

因此,您要么需要为 32 位编译应用程序,要么必须创建 64 位版本的 DLL。

【讨论】:

此时,我只有 DLL(32 位)并且没有机会拥有另一个 DLL - 64 位版本,同时我的 .NET 应用程序必须编译为任何 CPU(考虑 64也有点)。 soo,这个案子没有解决办法吗? 好吧,正如 Lasse V. Karlsen 建议的那样,您可以编写一个单独的 32 位应用程序(不是库!),您可以将其作为一个单独的进程启动并使用进程间通信“与之对话”。跨度> 【参考方案4】:

一个解决方案虽然有点混乱,但可能是编写一个单独的 32 位应用程序,您可以与您的 64 位应用程序进行通信,例如您向/从发送命令的控制台应用程序。

不漂亮,但如果您只需要偶尔调用它,它可能会起作用。

【讨论】:

我试过了,不完全一样,我写了 Class library,我在其中导入了 Delphi DLL,编译了 x86,然后我将它引用到我的 64 位主应用程序,但仍然没有运气。 因为它是同一个问题,只是更复杂。您的 64 位应用程序也不能使用 32 位类库! Mikael 谈论的是一个 32 位应用程序,您可以通过命名管道或其他 IPC 方法与之通信。 我读到可以通过 IPC 实现,但说实话,我还不太清楚.. 你有没有关于这方面的说明?我需要更多细节,因为这对我来说真的很新鲜【参考方案5】:

只需将您的 .Net 应用程序编译为 Platform x86。它将在 x64 机器上运行,并将使用您的 32 位 DLL。不要在包装上浪费时间。

【讨论】:

如果底层操作系统是 64 位,则不是一个选项,因为它会吞噬通过操作系统层的异常,您将看不到它们! 您曾梦想过哪种神奇的操作系统配置可以在 64 位操作系统上运行 32 位 .Net 应用程序,但会“吞下”异常... 这不是梦,而是我几个月的发展条件。我有一台 64 位开发机器,如果你为 x86 平台编译,异常会被吞没(来自并行任务,而不仅仅是)。 Visual Studio 仅在输出窗口中显示“第一次出现异常的机会”,显然您不会在运行的客户端应用程序中看到。原因:blog.paulbetts.org/index.php/2010/07/20/… Paul Betts 链接已失效,但 google 缓存有效:webcache.googleusercontent.com/search?q=cache:http://…

以上是关于在 64 位 .Net 应用程序中导入 32 位 dll的主要内容,如果未能解决你的问题,请参考以下文章

如何使 .NET 可执行文件在 64 位操作系统上作为 32 位进程运行?

将 32 位 VB.Net 连接到 64 位 Access .ACCDB

ride中导入autoitlibrary库以后,send关键字丢失

在 .NET 项目中同时引用 32 位和 64 位 dll 并单击一次 [重复]

在 64 位 .NET 应用程序中使用 32 位非托管 COM 服务器

为 Windows 编写跨平台(32 位和 64 位兼容)程序(如 .NET 中的 AnyCPU)