[翻译文章,原文请参考:http://www.codeproject.com/Articles/51326/Net-Compilation-registry-accessing-and-application.aspx]
多长的一个标题,不是吗?这是因为在一些情况下,你必需要做一大堆事情才能让你的.NET应用程序同时在x86和x64环境下成功运行,尤其是在你还需要使用一些非安全代码(unmanaged code)或者需要访问注册表的时候。
编译和运行.NET组件(Compiling and running assemblies)
原生代码(例如C++等等)都会被编译成为平台相关的二进制代码。这就是你在编译时候需要指定目标平台为x86或者x64的原因。在.NET平台下,情况有所不同。就与你可能已经知道的一样,你的VB或者C#代码并不会编译成为二进制代码,而是MSIL代码。这些代码加载时,JIT(Just-in-time)编译器负责把中间代码转化成为二进制代码。在这个转化过程中,编译器会根据当前操作系统来决定编译成32位代码还是64位代码。这就是你可以不给.NET组件指定目标平台,而选择"Any CPU"的原因。下面的图片是Visual Studio工程配置页的截图,你在这里可以选择目标平台。
既然如上所述,我为什么还要为.NET组件指定目标平台呢? "Any CPU"不应该是最好的选择吗? 是的。在绝大多数情况下,程序员开发的都是纯.NET应用程序,它不依赖任何非托管代码,也不需要进一步的优化。所以"Any CPU"是最好的选择(让JIT编译器动态确定编译成什么样的代码)。但是仍然有些情况你会想去指定目标平台,例如:
- 如果你使用了任何非托管代码(它是平台相关的),就需要注意目标平台的问题。因为当JIT编译器选择了一个和你的非托管代码不兼容的模式去做编译时,你的应用程序可能无法加载这些非托管代码。
- 如果你想对你的代码做平台相关优化。例如,你的应用程序需要做大量的RAM内存访问时,你可能只想让它运行在64位模式下。
另外,还有其他和目标平台相关的问题,比如注册表访问。我们会在这篇文章的后面讨论它。这篇博文对目标平台有进一步的讨论。
平台兼容性(Platform compatibility)
- 如果你的.NET组件使用"Any CPU"选项编译
-
- 它可以运行在X86环境中(JIT编译器把它编译成X86二进制代码)
- 它可以运行在X64环境中(JIT编译器把它编译成X64二进制代码)
- 如果你的.NET组件使用"X64"作为目标平台编译
-
- 它不可以运行在X86环境中
- 它可以运行在X64环境中
- 如果你的.NET组件使用"X86"作为目标平台编译
-
- 它可以运行在X86环境中
- 它可以运行在X64环境中(在WOW64模式下)
WOW64模式
因为向后兼容对于产品销售很有帮助,所以Windows 64位操作系统提供了一个为运行32位应用程序的兼容模式。它被称为WOW模式(Windows on Windows)。你有使用模拟器在PC上玩过电视游戏吗?它就类似这个模拟器。WOW64是一个在64位机器上运行32位应用程序的模拟器。尽管我们还会在后面讨论一些关于WOW64模式的问题,你可以先访问这里来了解WOW模式的更多细节。
检测"Any CPU"进程的位数(Detecting the bitness of a "Any CPU" process)
当你把.NET组件编译成为"Any CPU"时,会发生什么事情呢?如果你知道这个.NET组件总是运行在X86环境下,那运行这个组件的进程也会是32位的。但是如果这个.NET组件可以运行在X86和X64环境下,那运行这个组件的进程是32位还是64位呢?更进一步说,如果它运行在X64操作系统上,JIT编译器会选择32位还是64位来编译它呢?一般来说,它是64位的。但是怎样能够检测到这个呢?很简单,如下代码所示:
if (IntPtr.Size == 4)
return eArchitecture.x86;
else if
(IntPtr.Size == 8)
return eArchitecture.x64;
System.IntPtr被设计用来保存内存地址的。在.NET中,它提供了一个非常方便的属性告诉我们它的长度。因此,如果它的长度是8个字节,我们就是在用64位地址。如果是4字节,我们就在32位环境中。就是如此简单!
注意:如果你的组件编译时选择X86为目标平台,运行它的进程永远都是32位。即使运行在64位环境中,它使用的是WOW64模式(模拟32位),并且仍然是32位进程