操作系统版本和位数检测的C#实现

在开发软件时,经常需要知道程序运行的操作系统版本和位数,以便进行相应的适配和优化。本文将介绍如何使用C#编写程序来检测Windows操作系统的版本和位数。

在尝试查找检测Windows版本和位数的代码时,发现很多代码都没有更新到Windows 7,并且它们都没有包含所有可用的Windows版本(尤其是缺少“Professional”版本,这是常用的操作系统版本)。此外,它们都没有正确地确定操作系统是32位还是64位。在寻找解决方案的过程中,找到了一篇很好的文章:,认为这是最好的、最新的版本。所以决定修改这篇文章的代码,添加缺失的部分。

所做的更改

添加了对“Windows 7”和“Windows Server 2008 R2”的检测。添加了所有能发现的缺失的Windows版本。完全重写了32/64位检测代码。

如何使用代码

创建的类非常容易使用。只需将CS文件包含到项目中(或者将其编译为DLL以在VB项目中使用),然后像这样查询属性:

StringBuilder sb = new StringBuilder(String.Empty); sb.AppendLine("Operation System Information"); sb.AppendLine("----------------------------"); sb.AppendLine(String.Format("Name = {0}", OSVersionInfo.Name)); sb.AppendLine(String.Format("Edition = {0}", OSVersionInfo.Edition)); if (OSVersionInfo.ServicePack != string.Empty) sb.AppendLine(String.Format("Service Pack = {0}", OSVersionInfo.ServicePack)); else sb.AppendLine("Service Pack = None"); sb.AppendLine(String.Format("Version = {0}", OSVersionInfo.VersionString)); sb.AppendLine(String.Format("ProcessorBits = {0}", OSVersionInfo.ProcessorBits)); sb.AppendLine(String.Format("OSBits = {0}", OSVersionInfo.OSBits)); sb.AppendLine(String.Format("ProgramBits = {0}", OSVersionInfo.ProgramBits)); textBox1.Text = sb.ToString();

检测操作系统位数的难点

检测操作系统是32位还是64位实际上是一个很大的问题。发现很多建议的方法都不能正确工作。为了那些感兴趣以及为了学习和分享信息,将在这里列出不同的建议:

最流行的方法似乎是这种方法的变体:

return IntPtr.Size * 8;

但这实际上并没有返回操作系统的位架构,它返回的是运行程序的位值。所以对于在64位Windows上以32位模式运行的程序,上述代码将返回32。

另一种误导性很大的方法是:

string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64);

实际上,这个结果与版本1完全相同:它没有返回PROCESSOR_ARCHITECTURE名称所说的处理器位架构,而是返回了运行程序的位架构。对于在64位Windows上以32位模式运行的程序,上述代码也将返回32。

请注意:为了保持文章的合理长度,没有包含结构声明和PInvoke API声明……它们可以在源代码中找到。

ProcessorArchitecture pbits = ProcessorArchitecture.Unknown; try { SYSTEM_INFO l_System_Info = new SYSTEM_INFO(); GetSystemInfo(ref l_System_Info); switch (l_System_Info.uProcessorInfo.wProcessorArchitecture) { case 9: // PROCESSOR_ARCHITECTURE_AMD64 pbits = ProcessorArchitecture.Bit64; break; case 6: // PROCESSOR_ARCHITECTURE_IA64 pbits = ProcessorArchitecture.Itanium64; break; case 0: // PROCESSOR_ARCHITECTURE_INTEL pbits = ProcessorArchitecture.Bit32; break; default: // PROCESSOR_ARCHITECTURE_UNKNOWN pbits = ProcessorArchitecture.Unknown; break; } } catch { Ignore } return pbits;

再次失望。这段代码——尽管有处理器特定的标志——也返回了运行程序的位,而不是操作系统和处理器的位。

在某个地方读到,上述方法不可信(正如已经发现的),应该使用GetNativeSystemInfo API。

代码与上述代码完全相同,但是GetSystemInfo被GetNativeSystemInfo替换,API声明也是如此。

现在又得到了另一个结果。但遗憾的是,这个API似乎返回了处理器本身的位架构。感兴趣的是操作系统的位架构。可以很容易地在64位处理器的机器上运行32位的Windows版本。

所以还没有完成。

经过大量的研究,找到了决定在类中使用的方法:IntPtr.Size和IsWow64Process的组合:

static public SoftwareArchitecture OSBits { get { SoftwareArchitecture osbits = SoftwareArchitecture.Unknown; switch (IntPtr.Size * 8) { case 64: osbits = SoftwareArchitecture.Bit64; break; case 32: if (Is32BitProcessOn64BitProcessor()) osbits = SoftwareArchitecture.Bit64; else osbits = SoftwareArchitecture.Bit32; break; default: osbits = SoftwareArchitecture.Unknown; break; } return osbits; } } 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; }

如果IntPtr大小是64,则操作系统必须是64位的,因为不能在32位操作系统上运行64位程序。

如果程序以32位运行,则代码检查代码运行的过程以确定那是32位还是64位。

如果是64位,则操作系统将是64位的,但程序以32位运行。如果是32位,则操作系统也是32位的。

最后,将这些方法中的大多数包含在最终的类库中,因为能够区分程序、操作系统和处理器的位架构是很有用的。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485