获取操作系统版本信息 - 甚至适用于 Windows 10!
获取操作系统版本和版本,已更新至 Windows 10
引言
我一直在寻找一种方法来确定我的程序正在运行的操作系统的版本。当我用谷歌搜索时,我得到了很多代码片段,但它们都有同一个问题:它们没有为 Windows 7 更新。
此外,它们都有相同的两个缺点:
- 它们没有包含所有可用的 Windows 版本(尤其是“专业版”的缺失困扰了我,因为那是我通常使用的操作系统版本)。
- 我想知道操作系统是 32 位还是 64 位,而我找到的解决方案都无法正确确定。稍后将详细介绍...
背景
我找到了这篇文章 http://www.csharp411.com/determine-windows-version-and-edition-with-c/,在我看来,这是最好也是最新的版本。所以我决定简单地修改那段代码,并添加缺失的部分。
请注意:原始代码的所有功劳都归功于“TIMM”,即上述文章的作者...
我所做的修改
- 我在检测方案中添加了“Windows 7”和“Windows Server 2008 R2”。
- 我添加了所有我能找到的缺失的 Windows 版本。
- 完全重写了 32/64 位检测代码。
Using the Code
我提出的类非常易于使用。只需将 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 位。如前所述,我找到了许多关于如何检测的建议,但没有一个能正常工作。对于有兴趣的人,以及为了学习/分享信息,我将在下面列出不同的建议:
- 使用
IntPtr
大小最流行的方法似乎是基于这个的变种:
return IntPtr.Size * 8;
但这段代码实际上返回的是运行程序的位数,而不是操作系统的位数架构。因此,对于在 64 位 Windows 上以 32 位模式运行的程序,上面的代码将返回 32。
- 使用 '
PROCESSOR_ARCHITECTURE
' 环境变量string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64);
这实际上非常具有误导性,因为它的结果与第一个方法完全相同:它返回的是运行程序的位数,而不是处理器本身的位数架构。对于在 64 位 Windows 上以 32 位模式运行的程序,上面的代码也将返回 32。
- 使用
PInvoke
和GetSystemInfo
请注意:为了使文章长度合理,我没有包含结构声明和 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;
再次令人失望。这段代码——尽管存在处理器特定的标志——也返回的是运行程序的位数,而不是操作系统或处理器的位数。
- 使用
PInvoke
和GetNativeSystemInfo
我在某处读到,上述方法(正如我早已发现的那样)不应被信任,而应该使用
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 位。
最终,我在最终的类库中包含了大部分这些方法,因为能够区分程序、操作系统和处理器的位数架构可能会很有用。
致谢
感谢 Member 7861383,Scott Vickery 提供了 Windows 8.1 更新和解决方法。
感谢 Brisingr Aerowing 协助完成 Windows 10 的适配。
历史
- 2016-02-11 - 版本 3.0,添加了 Windows 8.1 和 Windows 10 的代码
- 2012-11-21 - 版本 2.0,添加了 Windows 8 和 Windows Server 2012 的版本号
- 2010-04-15 - 版本 1.0,首次发布