使用X86和Any CPU的C#项目

9

假设我有两个 Winform 项目 A 和 B。

项目 A(目标 .NET 2.0)必须在 x86 上运行(它是一个外部库),出于传统原因,项目 B(目标 .NET 4.0)必须在任何 CPU 上运行。现在,我需要从项目 B 调用 A 的方法,但会抛出错误:

"An unhandled exception of type 'System.BadImageFormatException' occurred in System.Windows.Forms.dll"

Additional information: Could not load file or assembly 'CSharpDemo, Version=1.0.5414.18636, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format."

然而,我发现如果我将项目B定位于.NET 4.5,则不会出现此问题。但我仍希望项目B定位为4.0,如何实现?


大多数情况下,它应该在32位机器上运行,但我不能将项目B的设置更改为x86,因为这可能会影响其他项目。 - dcc
1
看起来是死胡同。在64位操作系统上使用AnyCPU表示使用64位代码,而64位代码无法调用32位库。http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/ - Steve
我明白了,所以.NET 4.5能够成功运行的原因是因为它的“任何CPU 32位优先”设置,我想知道如何让.NET 4.0实现相同的效果? - dcc
这没有意义。你的意思是:
  1. 项目A需要调用项目B的方法
  2. 项目A需要在x86上运行
  3. 项目B需要在任何CPU上运行
- codenheim
@Steve:我认为Sasha在那篇博客文章中漏掉了几个重要的场景 :( - Ben Voigt
显示剩余3条评论
2个回答

11
如果你的代码调用32位x86库,整个进程都需要作为x86加载。没有任何例外。
要做到这一点,将EXE项目设置为x86,将具有本地x86依赖项的DLL项目设置为x86,对于纯管理DLL项目,您可以使用AnyCPU——.NET将它们作为x86加载到您的x86 EXE中,但它们也可以加载到x64 EXE中。
请记住,在运行x64 Windows的x64处理器上,通过WOW64兼容性层的帮助,x86代码可以正常运行。
(有少量例外:在Windows Server版中,WOW64是可选组件,在预安装环境中不存在WOW64)。

你所说的 EXE 项目是指 Visual Studio 中的启动项目吗?除了 x86 库之外,我所有的东西都使用 AnyCPU,因此这意味着我只需要将启动项更改为 x86,其余部分保持不变,对吗? - dcc
@wuha:创业项目将是一个EXE项目。有时一个解决方案有多个EXE,但你的主程序肯定是一个EXE。 - Ben Voigt
良好的回答 @BenVoigt - Steve

7
你可以在以下博客文章中找到你问题的答案:http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/ 以下是概要:
.NET 4.0
AnyCPU在.NET 4.0(和Visual Studio 2010)之前的含义如下: •如果进程运行在32位Windows系统上,则作为32位进程运行。 IL被编译为x86机器码。 •如果进程在64位Windows系统上运行,则作为64位进程运行。 IL被编译为x64机器码。 •如果进程在Itanium Windows系统上运行(有人有吗?;-)),则作为64位进程运行。 IL被编译为基于Itanium的机器码。
.NET 4.5
在.NET 4.5和Visual Studio 11中移动了部分设置。大多数.NET项目的默认设置再次为AnyCPU,但现在有不止一种AnyCPU的含义。“任何CPU 32位首选”是新的默认值(总体而言,现在有五个/platform C#编译器开关选项:x86、Itanium、x64、anycpu和anycpu32bitpreferred)。当使用该任何CPU时,其语义如下: •如果进程运行在32位Windows系统上,则作为32位进程运行。 IL被编译为x86机器码。 •如果进程在64位Windows系统上运行,则作为32位进程运行。 IL被编译为x86机器码。 •如果进程在ARM Windows系统上运行,则作为32位进程运行。 IL被编译为ARM机器码。

那么这意味着在.NET 4.0下,无法从“任何CPU”项目中调用x86项目的方法? - dcc
虽然你可以在 .NET 4.0 和 4.5 中编译相同的代码,并在项目中使用适当的程序集。 - Mayank
@wuha:在任何 .NET 版本中,都无法从非 x86 EXE 中使用 x86 DLL。在 .NET 4.5 中,由于新默认设置,您的项目正在以 x86 加载。 - Ben Voigt
@BenVoigt 即使程序最终在32位机器上运行,AnyCPU也应该相应地适用于x86吧? - dcc
1
@wuha:AnyCPU 不是一种单独的架构,而是表示文件遵循环境选择的架构。有时它会选择 x86,这是必需的,这样事情就能顺利运行。但是每当 AnyCPU 的灵活性发挥作用,选择了某些非 x86 的架构时,您的 x86 依赖项将无法加载。 - Ben Voigt

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