【问题标题】:System.BadImageFormatException when compiled using any cpu使用任何 cpu 编译时出现 System.BadImageFormatException
【发布时间】:2019-12-23 23:05:14
【问题描述】:

当我使用“任何 CPU”编译应用程序时,每当我尝试使用 Firebird 嵌入式 dll 打开连接时,我都会收到System.BadImageFormatException(不要问我为什么仍在使用这个遗留数据库。不是我的选择)

然后我想一定是dll只支持32bit模式。所以我尝试使用 x86 进行编译,这次确实运行良好。

但是,当我使用 x64 编译时,应用程序仍然运行良好。这让我很困惑,因为它清楚地表明 dll 能够以 64 位模式加载。

我做了几个测试,结果如下:

任何 CPU:64 位进程。 System.BadImageFormatException
x86:32 位进程。运行良好
x64:64 位进程。运行良好
任何 CPU(首选 32 位):32 位进程。运行良好

我认为 Any CPU 的唯一魔力是它会在启动期间选择是否以 32/64 位模式启动进程。如果应用程序在严格的 64 位模式下运行良好,那么我希望任何 CPU 在同一台 64 位机器上运行良好。

我还是更喜欢使用 Any CPU(不带首选 32 位标志),因为它使分发更容易。

什么可能导致异常,有没有办法处理它?

编辑:
所以我尝试使用反射来获取程序集信息,这是我得到的错误消息

使用“1”个参数调用“GetAssemblyName”的异常:“不能 加载文件或程序集“fbembed.dll”或其依赖项之一。这 模块应该包含一个程序集清单。”在 line:1 char:1 + [reflection.assemblyname]::GetAssemblyName("${pwd}\fbembed.dll") |佛罗里达州 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : BadImageFormatException

【问题讨论】:

  • 检查在每种情况下加载的组件图像。它是 32 和 64 中的相同图像吗(我猜这不是因为 32 位图像不能在 64 位进程中加载​​,反之亦然)。还要检查有问题的程序集上的元数据,IIRC 有 .Net 工具,但你可以使用 dotPeek 或类似工具(有一个我忘记名字的开源等价物)
  • 解决方案平台的名称与 C# 程序无关,架构和位数在运行时而非构建时确定。只有抖动偏好很重要。因此,始终将 AnyCPU 作为平台名称,使用 Project > Properties > Build 选项卡覆盖默认的抖动选项。 “首选 32 位”是您的首选。
  • @HansPassant but Prefer 32-bit 将在 32 位模式下启动应用程序,即使在 64 位机器上也不是我们想要的。
  • 这是一个非常令人费解的评论,因为您知道您使用的 dbase 提供程序不能在 64 位模式下运行。我无法对那个脑病进行逆向工程。
  • @HansPassant 如果我将整个解决方案设置为 64 位,它可以在 64 位模式下工作。只有 Any CPU 给我带来了麻烦。

标签: c# badimageformatexception


【解决方案1】:

在检查 dll 的标头后,发现 Nuget 是执行魔术的那个。如果我将目标设置为 x86/x64,nuget 将在编译期间包含相应版本的 dll。

但如果我以“任何 CPU”为目标,nuget 将选择 x86 版本的 dll。因此,如果我尝试以 64 位模式启动我的应用程序,它将抛出 BIFE。

【讨论】:

  • 这是我怀疑的,这就是我建议查看元数据的原因。不管怎样,很高兴你知道了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 1970-01-01
  • 2016-04-21
  • 2020-09-19
  • 1970-01-01
相关资源
最近更新 更多