我对 Visual Studio 2008 中的 .NET 平台构建选项有些困惑。
什么是“Any CPU”编译目标,它生成什么样的文件?我检查了这个“任何 CPU”构建的输出可执行文件,发现它们是 x86 可执行文件(谁不会看到它的到来!)。那么,将可执行文件定位到 x86 与“任何 CPU”之间有什么区别吗?
我注意到的另一件事是托管 C++ 项目没有此平台作为选项。这是为什么?这是否意味着我对“任何 CPU”可执行文件是普通的 32 位可执行文件的怀疑是正确的?
Any CPU
并且您在 64 位操作系统上运行,您将失去 的能力在调试时编辑并继续。 (您正在有效地调试 64 位进程)。您可以将 Startup project 设为目标 x86
以在调试时规避此问题。 (从启动项目引用的程序集可能会继续以 Any CPU
为目标。
AnyCPU
应用程序使用 x86
库时遇到了这个问题,我必须设置 Prefer 32-bit
以避免加载错误。
AnyCPU 程序集在加载到 64 位进程时将 JIT 到 64 位代码,当加载到 32 位进程时将 JIT 到 32 位代码。
通过限制 CPU,您会说:程序集使用的某些东西(可能是非托管的)需要 32 位或 64 位。
我想大部分重要的东西已经说了,但我只是想补充一点:如果你编译为 Any CPU 并在 x64 平台上运行,那么你将无法加载 32 位 DLL 文件,因为您的应用程序不是在 WoW64 中启动的,但那些 DLL 文件需要在那里运行。
如果您编译为 x86,则 x64 系统将在 WoW64 中运行您的应用程序,您将能够加载 32 位 DLL 文件。
因此,如果您的依赖项可以在任一环境中运行,我认为您应该选择“Any CPU”,但如果您有 32 位依赖项,请选择 x86。 Microsoft 的这篇文章对此进行了一些解释:
/CLRIMAGETYPE (Specify Type of CLR Image)
顺便说一句,this other Microsoft documentation 同意 x86 通常是更便携的选择:
选择 x86 通常是应用程序包最安全的配置,因为它几乎可以在所有设备上运行。在某些设备上,具有 x86 配置的应用程序包将无法运行,例如 Xbox 或某些 IoT Core 设备。但是,对于 PC,x86 包是最安全的选择,并且具有最大的设备部署范围。很大一部分 Windows 10 设备继续运行 x86 版本的 Windows。
下面是解释不同构建目标的 a quick overview。
根据我自己的经验,如果您希望构建一个可以在 x86 和 x64 平台上运行的项目,并且您没有任何特定的 x64 优化,我会将构建更改为专门说“x86”。
造成这种情况的原因是有时您可能会在 x64 环境中获得一些冲突的 DLL 文件或导致崩溃 WoW 的一些代码。通过专门指定 x86,x64 操作系统会将应用程序视为纯 x86 应用程序,并确保一切顺利运行。
查看文章Visual Studio .NET Platform Target Explained。
默认设置“任何 CPU”意味着程序集将在当前运行的 CPU 上本地运行。意思是,它将在 64 位机器上以 64 位运行,在 32 位机器上以 32 位运行。如果从 64 位应用程序调用程序集,它将作为 64 位程序集执行,依此类推。
上面的链接已经被报坏了,所以这里有另一篇类似解释的文章:What AnyCPU Really Means As Of .NET 4.5 and Visual Studio 11
“Any CPU”是指当程序启动时,.NET Framework 会根据操作系统的位数来确定是以 32 位还是 64 位运行您的程序。
x86 和 Any CPU 之间存在区别:在 x64 系统上,为 X86 编译的可执行文件将作为 32 位可执行文件运行。
就您的怀疑而言,只需转到 Visual Studio 2008 命令行并运行以下命令。
dumpbin YourProgram.exe /headers
它将告诉您程序的位数,以及更多信息。
任何 CPU 意味着它可以在任何平台上工作。这是因为托管代码类似于 Java。将其视为被编译为 .NET Framework 在运行时解释的字节码。
C++ 没有此选项,因为它被编译为特定于平台的机器代码。
我推荐阅读this post。
使用 AnyCPU 时,语义如下:
如果进程在 32 位 Windows 系统上运行,则它作为 32 位进程运行。 CIL 被编译成 x86 机器码。如果进程在 64 位 Windows 系统上运行,则它作为 32 位进程运行。 CIL 被编译成 x86 机器码。如果进程在 ARM Windows 系统上运行,它将作为 32 位进程运行。 CIL 被编译为 ARM 机器代码。