65.9K
CodeProject 正在变化。 阅读更多。
Home

轻松获取和比较操作系统版本信息

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (25投票s)

2005年5月25日

CPOL

7分钟阅读

viewsIcon

123654

downloadIcon

3822

一对类,可轻松无误地检查主机 OS 版本。

引言

我需要为我正在编写的应用程序检查主机操作系统版本。我想写类似这样的代码:

if ( OperatingSystemVersion.Current < OSVersionInfo.WinXP )
{
    MessageBox.Show( "Please upgrade your OS" );
    Application.Exit();
}

我在MSDN上查找,发现了许多链接。然而,我需要的信息分散在所有链接中,没有任何一个链接能做到我想要的。我找到最接近的.NET类是System.OperatingSystem,它可以通过Environment.OSVersion属性访问。这个类几乎能满足我的需求:它能获取一些关于操作系统的基本信息。但是,它不够完善;它不能获取我想要的所有信息,而且你需要了解微软版本系统的细节才能使用它。

我想把这一切都弄清楚,所以我编写了一个更高级别的抽象,它封装了自Windows 95以来的所有Windows操作系统的不同版本信息。代码只有1000行,但它实现了我想要的功能。它包含了System.OperatingSystem的所有属性,所以你使用它不会丢失任何东西。它还增加了新操作系统(如Service Pack编号)上可用的额外信息。

因此,这个项目使得上面的代码成为可能,同时也暴露了主机操作系统所有可用的属性,如果你想获取更多细节的话。

Using the Code

要使用该代码,你可以将源代码文件(Common/OSVersion.cs)包含在你的C#项目中,或者将库文件(Common.OSVersion.dll)复制到你的项目中并添加一个引用。这些类都在Common命名空间下。上面的代码可以按原样工作。OSVersionInfo类中有15个static对象,涵盖了所有32位和64位Windows操作系统。它们是:

public class OSVersionInfo : IComparable, ICloneable
{
    ...
    
    public static OSVersionInfo Win32s     { get; }
    public static OSVersionInfo Win95      { get; }
    public static OSVersionInfo Win98      { get; }
    public static OSVersionInfo WinME      { get; }
    public static OSVersionInfo WinNT351   { get; }
    public static OSVersionInfo WinNT4     { get; }
    public static OSVersionInfo Win2000    { get; }
    public static OSVersionInfo WinXP      { get; }
    public static OSVersionInfo Win2003    { get; }
    public static OSVersionInfo WinXPx64   { get; }
    public static OSVersionInfo WinCE      { get; }
    public static OSVersionInfo Vista      { get; }
    public static OSVersionInfo Win2008    { get; }
    public static OSVersionInfo Win2008R2  { get; }
    public static OSVersionInfo Win7       { get; }
    
    ...
}

你也可以在你的测试中使用任何比较运算符(==, !=, <=, >=, <, >),或者你可以使用EqualsCompareTo方法。如果你只想做这些,那么你可以跳过本文的其余部分:)

=== 更新 v3 ===

XP x64和2003的版本号(主版本号和次版本号)是相同的 == 5.2。Vista和2008也是如此 == 6.0,2008 R2和Win7也是如此 == 6.1。如果你需要区分这些系统,你可以检查OSVersionInfo.OSProductType属性是否等于OSProductType.Workstation

OperatingSystemVersion

这个类继承自主OSVersionInfo类。它不添加任何属性;它所做的就是在其构造函数中用当前主机的值填充基类OSVersionInfo对象。它使用PInvoke调用GetVersionEx,使用OSVERSIONINFOOSVERSIONINFOEX结构来获取此信息。

OSVersionInfo

这是你最常使用的类。它保存了关于操作系统所有可用信息,并通过属性公开。如果OSVersionInfo类的所有属性和方法无法完成,它们都可能抛出InvalidOperationException。我将属性分为几个部分:

状态属性

这些属性处理OSVersionInfo对象的状态。它们是:

public bool IsLocked { get; }

如果此属性为true,则该对象被“锁定”,并且调用set方法将抛出异常。你可以在构造函数中lock一个实例或调用Lock()方法。你不能“解锁”一个实例,除非通过复制它(然后副本是未锁定的)。

public bool ExtendedPropertiesAreSet { get; set; }

扩展属性仅由OperatingSystemVersion构造函数设置,前提是主机操作系统为NT4 SP6或更高版本。如果你在ExtendedPropertiesAreSetfalse时调用扩展属性的get方法,将抛出异常。

普通属性

这些属性提供对底层字段的直接访问,并适用于所有操作系统。它们是:

public Common.OSPlatformId OSPlatformId { get; set; }

此属性返回一个OSPlatformId,它是一个enum。有四个值:

public enum OSPlatformId
{
    Win32s           =  0, // Win32s        
    Win32Windows     =  1, // Win95, Win98, WinME
    Win32NT          =  2, // WinNT351, WinNT4, Win2000, WinXP, Win2003, Vista
    WinCE            =  3, // WinCE
}

请注意,WinCE被定义为“最新”的操作系统。

public int OSMajorVersion { get; set; }

这是主版本号。可能的数值请参见OSValues

public int OSMinorVersion { get; set; }

这是次版本号。可能的数值请参见OSValues

public int BuildNumber { get; set; }

这是Build编号。我找不到可能的数值列表,但这会随着每个Service Pack而变化。我已经开始了一个相关的enum,名为OSBuildNumber,但目前只有三个值。(我只有三个系统的访问权限。)

public enum OSBuildNumber
{
    None = 0,
    Win2000SP4 = 2195,
    WinXPSP2   = 2600,
    Win2003SP1 = 3790,
}

注意:如果你有不同版本系统的访问权限,并且愿意通过电子邮件向我发送你的系统Build编号,我将不胜感激。你可以通过运行演示程序OSVersionDemo来获取Build编号。然后,我将更新本文档,包含相应的数值。我特别需要NT4 SP6的Build编号,因为它是第一个支持扩展信息的操作系统。

public string OSCSDVersion { get; set; }

这是一个string,例如“Service Pack 3”,表示系统中安装的最新Service Pack。如果没有安装Service Pack,则该string为空。

扩展属性

这些属性提供对底层字段的直接访问,但仅适用于包括NT4 SP6或更高版本的操作系统。你可以通过获取ExtendedPropertiesAreSet属性的值来检查这些属性是否可用。如果你尝试在ExtendedPropertiesAreSetfalse时访问这些属性,它们将抛出异常。它们是:

public Commmon.OSSuites OSSuiteFlags { get; set; }

此属性是OSSuites enum的位组合

[ Flags ]
public enum OSSuites
{
    None                     =  0,
    SmallBusiness            =  0x00000001,
    Enterprise               =  0x00000002,
    BackOffice               =  0x00000004,
    Communications           =  0x00000008,
    Terminal                 =  0x00000010,
    SmallBusinessRestricted  =  0x00000020,
    EmbeddedNT               =  0x00000040,
    Datacenter               =  0x00000080,
    SingleUserTS             =  0x00000100,
    Personal                 =  0x00000200,
    Blade                    =  0x00000400,
    EmbeddedRestricted       =  0x00000800,
}

正如你所见,这些值大多适用于服务器系统。

    public Commmon.OSProductType OSProductType { get; set; }

此属性是一个OSProductType

public enum OSProductType
{
    Invalid          = 0,
    Workstation      = 1,
    DomainController = 2,
    Server           = 3,
}

这些值区分了操作系统家族的不同类型。

public Int16 OSServicePackMajor { get; set; }

此属性是已应用的最新Service Pack的主版本号。如果没有安装Service Pack,则值为零。

public Int16 OSServicePackMinor { get; set; }

此属性是已应用的最新Service Pack的次版本号。如果没有安装Service Pack,则值为零。

public byte OSReserved { get; set; }

此属性保留供将来使用。

底层属性

这些属性允许访问OSVERSIONINFOOSVERSIONINFOEX结构中的底层值。它们是为了与System.OperatingSystem类兼容而提供的。

public int Platform { get; }

此属性是操作系统的PlatformId。参见OSPlatformId

public int SuiteMask { get; }

此属性是一个位标志值,用于标识系统中可用的产品套件。参见OSSuiteFlags

public byte ProductType { get; }

此属性提供有关系统的附加信息。参见OSProductType

计算属性

这些属性是从底层字段计算出来的(因此不能设置)。

public System.Version Version { get; }

此属性是为了与System.OperatingSystem类兼容而提供的。

public Common.OSVersion OSVersion { get; }

此属性非常有用。它根据OSPlatformIdOSMajorVersionOSMinorVersion计算操作系统版本。有关详细信息,请参见OSValues。它返回一个Common.OSVersion,它是一个enum

public enum OSVersion
{
    Win32s,
    Win95,
    Win98,
    WinME,
    WinNT351,
    WinNT4,
    Win2000,
    WinXP,
    Win2003,
    WinXPx64,
    WinCE,
    Vista,
    Win2008,
    Win2008R2,
    Win7,
}

enum指定了15种Windows操作系统版本之一。

字符串属性

这些属性返回某些属性的string表示形式。

public string VersionString       { get; }
public string OSPlatformIdString  { get; }
public string OSSuiteString       { get; }
public string OSProductTypeString { get; }
public string OSVersionString     { get; }

Object.ToString()方法也已重写,并提供操作系统的完整描述。

关注点

这段代码只是一个低级方法的包装器,用于提供对细节的有用抽象。它不是很有趣的代码,但它做得很好——至少我认为是这样。:)

最困难的部分是找到足够的信息来区分不同的版本。我现在已经做到了,所以你不需要了。:)

OSValues

出于兴趣,以下是15种32位和64位Windows操作系统的PlatformId、主版本号和次版本号:

+------------+------------+-------+-------+---------+
| Version    | PlatformId | Major | Minor | Release |
+------------+------------+-------+-------+---------+
| Win32s     |      0     |   ?   |   ?   |         |
| Win95      |      1     |   4   |   0   | 1995 08 |
| Win98      |      1     |   4   |  10   | 1998 06 |
| WinME      |      1     |   4   |  90   | 2000 09 |
| WinNT351   |      2     |   3   |  51   | 1995 04 |
| WinNT4     |      2     |   4   |   0   | 1996 07 |
| Win2000    |      2     |   5   |   0   | 2000 02 |
| WinXP      |      2     |   5   |   1   | 2001 10 |
| Win2003    |      2     |   5   |   2   | 2003 04 |
| WinXPx64   |      2     |   5   |   2   | 2003 03 |
| WinCE      |      3     |   ?   |   ?   |         |
| Vista      |      2     |   6   |   0   | 2007 01 |
| Win2008    |      2     |   6   |   0   | 2008 02 |
| Win2008R2  |      2     |   6   |   1   | 2009 10 |
| Win7       |      2     |   6   |   1   | 2009 10 |
+------------+------------+-------+-------+---------+

这是OSVersionInfo类所封装的数据。使用此类比在解决方案中硬编码这些值更容易,也更不容易出错。

参考文献

解读操作系统版本号所需的信息分散在MSDN中。以下是我使用的一些来源:

Platform SDK

知识库

.NET Framework

正如你所见,微软并没有让这件事变得容易。:)

一如既往,Lutz Roeder的Reflector [^]和PInvoke.net [^] Wiki都非常有帮助。

历史

  • 2010年3月29日:版本3 - 支持2008、2008 R2和Win7
  • 2008年1月3日:版本2 - 支持XP x64和Vista
  • 2005年5月25日:版本1 - 支持到2003
© . All rights reserved.