C#编译为32位/64位,或任何CPU的难题

10
这个问题与SO上的这些先前问题有关:Any CPU question 1Any CPU Question 2
我有一个应用程序,最初是在Win XP上使用Visual Studio 2005构建的(别笑!)。该应用程序调用我们的win32 C ++ dll。调用C ++ dll的C#组件使用“Any CPU”配置构建,并且在Win XP上正常工作。
我们现在正在转移到Win 7,并且使用VC 2005在Win XP上构建的发布版本的应用程序可以正常工作。但是,随着我们向用户推出win 7,我们已经利用了机会使用VS 2010,并且我已经在win 7上使用VC 2010构建了C#组件,但现在运行此版本时,我获得了许多“无法加载abc.dll”其中abc.dll是我们的win32 c ++组件。
我知道使用x86配置重新编译C#程序集将解决问题,但我不明白的是,使用Win-XP / Visual studio 2005(Any CPU配置)构建的C#程序集如何在Win 7上运行而没有任何问题?毕竟,当在Win 7中加载它们并调用Win32 C ++ dll时,使用“Any CPU”的这些C#程序集应该JIT到64位代码并导致BadImageFormatException或其他错误。
更新:我有一些在下面的评论中请求的更多信息。
  1. 在我的Windows 7框上,右键单击我的电脑,查看属性。系统信息显示“系统类型:64位操作系统”,证实这是Win64 OS。
  2. 在Windows XP上使用VC2005打开解决方案时,在查看解决方案的配置管理器时,我可以确认所有C#项目都是平台类型“Any CPU”。
  • 在64位Win 7机器上运行发布版本(该版本是使用VC2005 / win xp制作的)时,任务管理器显示图像名称为“ Test.exe *32”,这证实它已经被jit编译并加载到32位进程中。


  • 1
    目标环境的位数在两种情况下是否相同?这可能是另一个隐蔽的变化正在发生? - user166390
    这里还有一些你没有告诉我们的事情。在64位系统上,AnyCPU程序集将成为64位进程。它的构建位置并不重要。 - David Heffernan
    3
    只有 EXE 项目中的平台目标设置才是关键,它决定了进程的位数。请注意,在“生成”+“配置管理器”中的活动平台选择不适用于受管项目。 - Hans Passant
    哦哦!在使用 XP/VS2005 组合进行构建时,在 Windows 7 中使用任务管理器检查位数。如果你的 exe 处于 *32 加载状态,则为 32 位,否则为 64 位。请告知是否将 XP/VS2005 构建设置为 32 或 64 位执行。 - Joshua
    你确定你的 Windows 7 系统是 64 位的吗?毕竟,并不是所有的 Windows 7 安装程序都是 64 位的。 - Joel Coehoorn
    请参见上文获取更多信息。 - Ted
    3个回答

    4
    在Windows 7操作系统下,该进程是64位的。64位进程不能包含32位DLL文件,这是Windows的一个非常基本的设计限制。
    而且,这个托管代码的可执行文件调用了一个32位DLL文件,并不是显而易见的——P/Invoke和COM互操作通过延迟绑定工作。因此,可执行文件被加载后,加载器不会检查依赖项——首先,依赖项可能是有条件的,然后DLL文件加载时出现了诡异情况。
    所以,如果您的托管代码已知具有32位依赖项,最好在编译时指定32位CPU。或者将C++部分重新编译为64位,这也是一种选择。

    4
    那么为什么他在使用VS2005时不需要指定32位呢? - Branko Dimitrijevic
    3
    谢谢Seva,但你没有抓住重点,Branko理解了: 问题是为什么在Win XP/VC2005上用“任何CPU”构建时可以运作,但在Win 7/VC2010上用“任何CPU”构建时却无法运行。 - Ted
    也许构建机器的位数会影响EXE图像...不确定 :) 从问题中并不清楚在Win7上进行VS2005构建的结果会是什么。 - Seva Alekseyev
    @Seva "也许构建机器的位数会影响EXE镜像。" 不是的,“从问题中并不明显能够知道在Win7上进行VS2005构建的结果会是什么。” 是的,AnyCPU目标在x64系统上运行x64,在x86系统上运行x86。 - David Heffernan
    2
    你的意思不是:“这是任何操作系统的一个非常基本的限制”吗? - Jonathan Dickinson

    2

    我可以确认你应该会收到BadImageFormatException错误。是否有可能在XP上编译时被严重修改,导致它实际上不是构建AnyCPU,而是标记为AnyCPU的x86构建。我还可以确认,可能会对项目文件进行恶意操作,以至于它会这样做,而项目升级组件则无法处理。


    “monkeyed”…这是一个新的技术术语吗? :-) 通过“monkeyed”,我理解你的意思是编译成了IL代码? - Ted

    1

    可能的解释之一是,在32位开发系统上,您的解决方案中的一个项目具有对32位程序集的二进制引用,这将强制它在64位系统上作为32位进程加载。


    如果我的程序入口点在一个 C# 可执行文件中,那么它肯定必须被 JIT 编译成 32 位/64 位可执行文件,并首先加载到适当的进程中。随后对 win32 的调用(无论如何都是后期绑定)应该会生成一个异常(bad image Format)……或者我漏掉了什么? - Ted
    根据我的经验,尽管本地DLL确实是后期绑定的,如果位数不匹配,它们会生成您提到的异常,但对编译为32位的托管DLL的非项目引用确实会强制该进程以32位应用程序启动。 - 500 - Internal Server Error

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接