在.NET 2.0 C#应用程序中,我使用以下代码来检测操作系统平台:
string os_platform = System.Environment.OSVersion.Platform.ToString();
这将返回"Win32NT".问题是,即使在Windows Vista 64位上运行,它也会返回"Win32NT".
有没有其他方法可以知道正确的平台(32或64位)?
请注意,在Windows 64位上作为32位应用程序运行时,它还应检测64位.
.NET 4在Environment类中有两个新属性,Is64BitProcess和Is64BitOperatingSystem.有趣的是,如果使用Reflector,您会发现它们在32位和64位版本的mscorlib中的实现方式不同.对于Is64BitProcess,32位版本返回false,并通过P/Invoke为Is64BitOperatingSystem调用IsWow64Process.64位版本只为两者返回true.
如果在64位Windows上运行32位.NET Framework 2.0(它将返回32位),IntPtr.Size将不会返回正确的值.
正如微软的Raymond Chen所描述的那样,你必须首先检查是否在64位进程中运行(我认为在.NET中你可以通过检查IntPtr.Size来实现),如果你在32位进程中运行,你仍然需要必须调用Win API函数IsWow64Process.如果返回true,则表示您在64位Windows上以32位进程运行.
微软的Raymond Chen: 如何以编程方式检测您是否在64位Windows上运行
我的解决方案
static bool is64BitProcess = (IntPtr.Size == 8); static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64(); [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWow64Process( [In] IntPtr hProcess, [Out] out bool wow64Process ); public static bool InternalCheckIsWow64() { if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6) { using (Process p = Process.GetCurrentProcess()) { bool retVal; if (!IsWow64Process(p.Handle, out retVal)) { return false; } return retVal; } } else { return false; } }
如果您使用的是.NET Framework 4.0,则很容易:
Environment.Is64BitOperatingSystem
请参见Environment.Is64BitOperatingSystem属性(MSDN).
这只是Bruno Lopez上面建议的实现,但适用于Win2k +所有WinXP服务包.刚刚想到我发布了它,所以其他人没有手动滚动它.(会发布评论,但我是新用户!)
[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr LoadLibrary(string libraryName); [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName); private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process); public static bool IsOS64Bit() { if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor())) { return true; } else { return false; } } private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate() { IntPtr handle = LoadLibrary("kernel32"); if ( handle != IntPtr.Zero) { IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process"); if (fnPtr != IntPtr.Zero) { return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate)); } } return null; } private static bool Is32BitProcessOn64BitProcessor() { IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate(); if (fnDelegate == null) { return false; } bool isWow64; bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64); if (retVal == false) { return false; } return isWow64; }
完整的答案就是这个(取自stefan-mg,ripper234和BobbyShaftoe的回答):
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo); private bool Is64Bit() { if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor())) { return true; } else { return false; } } private bool Is32BitProcessOn64BitProcessor() { bool retVal; IsWow64Process(Process.GetCurrentProcess().Handle, out retVal); return retVal; }
首先检查您是否处于64位进程中.如果不是,请检查32位进程是否为Wow64Process.
微软为此提供了一个代码示例:
http://1code.codeplex.com/SourceControl/changeset/view/39074#842775
它看起来像这样:
////// The function determines whether the current operating system is a /// 64-bit operating system. /// ////// The function returns true if the operating system is 64-bit; /// otherwise, it returns false. /// public static bool Is64BitOperatingSystem() { if (IntPtr.Size == 8) // 64-bit programs run only on Win64 { return true; } else // 32-bit programs run on both 32-bit and 64-bit Windows { // Detect whether the current process is a 32-bit process // running on a 64-bit system. bool flag; return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(GetCurrentProcess(), out flag)) && flag); } } ////// The function determins whether a method exists in the export /// table of a certain module. /// /// The name of the module /// The name of the method ////// The function returns true if the method specified by methodName /// exists in the export table of the module specified by moduleName. /// static bool DoesWin32MethodExist(string moduleName, string methodName) { IntPtr moduleHandle = GetModuleHandle(moduleName); if (moduleHandle == IntPtr.Zero) { return false; } return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero); } [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)]string procName); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
还有一个WMI版本(用于测试远程机器).
您还可以检查PROCESSOR_ARCHITECTURE
环境变量.
它要么不存在,要么在32位Windows上设置为"x86".
private int GetOSArchitecture() { string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64); }
来自Chriz Yuen博客
C#.Net 4.0引入了两个新的环境属性Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;
使用这两个属性时请小心.在Windows 7 64位机器上测试
//Workspace: Target Platform x86 Environment.Is64BitOperatingSystem True Environment.Is64BitProcess False //Workspace: Target Platform x64 Environment.Is64BitOperatingSystem True Environment.Is64BitProcess True //Workspace: Target Platform Any Environment.Is64BitOperatingSystem True Environment.Is64BitProcess True
最快的方式:
if(IntPtr.Size == 8) { // 64 bit machine } else if(IntPtr.Size == 4) { // 32 bit machine }
注意:这是非常直接的.
试试这个:
Environment.Is64BitOperatingSystem Environment.Is64BitProcess
@foobar:你说得对,太容易了;)
在99%的情况下,具有弱系统管理员背景的开发人员最终未能意识到微软一直为任何人提供枚举Windows的能力.
在涉及到这一点时,系统管理员总是会编写更好,更简单的代码.
不过,有一点需要注意,构建配置必须是AnyCPU才能使此环境变量在正确的系统上返回正确的值:
System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
这将在32位Windows上返回"X86",在64位Windows上返回"AMD64".
使用这两个环境变量(伪代码):
if (PROCESSOR_ARCHITECTURE = x86 && isDefined(PROCESSOR_ARCHITEW6432) && PROCESSOR_ARCHITEW6432 = AMD64) { //64 bit OS } else if (PROCESSOR_ARCHITECTURE = AMD64) { //64 bit OS } else if (PROCESSOR_ARCHITECTURE = x86) { //32 bit OS }
请参阅博客文章HOWTO:Detect Process Bitness.
使用dotPeek有助于了解框架实际上是如何实现的.考虑到这一点,这就是我想出的:
public static class EnvironmentHelper { [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll")] static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32")] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll")] static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process); public static bool Is64BitOperatingSystem() { // Check if this process is natively an x64 process. If it is, it will only run on x64 environments, thus, the environment must be x64. if (IntPtr.Size == 8) return true; // Check if this process is an x86 process running on an x64 environment. IntPtr moduleHandle = GetModuleHandle("kernel32"); if (moduleHandle != IntPtr.Zero) { IntPtr processAddress = GetProcAddress(moduleHandle, "IsWow64Process"); if (processAddress != IntPtr.Zero) { bool result; if (IsWow64Process(GetCurrentProcess(), out result) && result) return true; } } // The environment must be an x86 environment. return false; } }
用法示例:
EnvironmentHelper.Is64BitOperatingSystem();