Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#

Easily Get and Compare OS Version Information

Rate me:
Please Sign up or sign in to vote.
4.74/5 (28 votes)
30 Mar 2010CPOL7 min read 119.9K   3.8K   81   18
A couple of classes to make checking the host OS version easy and error-free

Introduction

I needed to check the host operating system version for an application I was writing. I wanted to be able to write something like this:

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

I looked in MSDN and found a lot of links. However, the information I needed was spread out across all the links and none of them did what I wanted. The closest .NET class I found was System.OperatingSystem, which is available through the Environment.OSVersion property. This class almost does what I wanted: it gets some information about the OS. However, it doesn't go far enough; it doesn't get all the information I wanted and you have to know the details of Microsoft's version system to use it.

I wanted to demystify all this, so I wrote a higher level abstraction that encapsulates all the different version information for all the Windows operating systems since Windows 95. It's only 1000 lines of code, but it makes what I wanted possible. It includes all the properties of System.OperatingSystem, so you don't lose anything by using it. It also adds the extra information available on later operating systems (like Service Pack numbers).

So this project makes the code above possible, while also exposing all the available properties of the host operating system if you want to get more details.

Using the Code

To use the code, you can either include the source file ( Common/OSVersion.cs ) in your C# project or copy the library ( Common.OSVersion.dll ) to your project and add a reference to it. The classes are all in the Common namespace. The code above works as-is. There are 15 static objects in the OSVersionInfo class, covering all the 32-bit and 64-bit Windows operating systems. These are:

C#
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; }
    
    ...
}

You can also use any of the comparison operators ( ==, !=, <=, >=, <, > ) in your test, or you can use the Equals and CompareTo methods. If this is all you want to do, then you can skip the rest of this article :)

=== UPDATE v3 ===

The version numbers (both major and minor) for XP x64 and 2003 are identical == 5.2. The same applies to Vista and 2008 == 6.0 and to 2008 R2 and Win7 == 6.1. If you need to differentiate between these systems, you can check the OSVersionInfo.OSProductType property against OSProductType.Workstation.

OperatingSystemVersion

This class derives from the main OSVersionInfo class. It doesn't add any properties; all it does is populate the base OSVersionInfo object with the current host values in its constructor. It uses PInvoke to call GetVersionEx, using either an OSVERSIONINFO or an OSVERSIONINFOEX structure to get this information.

OSVersionInfo

This is the main class that you will use most often. It holds all the available information about an operating system and makes this available through properties. All the properties and methods of this class can throw an InvalidOperationException if they cannot complete. I have grouped the properties into a few sections:

State Properties

These properties handle the state of the OSVersionInfo object. They are:

C#
public bool IsLocked { get; }

If this property is true, then the object is "locked" and the set methods will throw an exception if called. You can lock an instance in the constructors or call the Lock() method. You cannot "unlock" an instance except by copying it (then the copy is unlocked).

C#
public bool ExtendedPropertiesAreSet { get; set; }

The extended properties are only set by the OperatingSystemVersion constructor if the host operating system is NT4 SP6 or later. If you call the get method of an extended property when this value is false, an exception will be thrown.

Normal Properties

These properties provide direct access to the underlying fields and are available for all operating systems. They are:

C#
public Common.OSPlatformId OSPlatformId { get; set; }

This property returns an OSPlatformId, which is an enum. There are four values:

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

Note that WinCE is defined to be the "latest" operating system.

C#
public int OSMajorVersion { get; set; }

This is the Major Version number. See OSValues for possible values.

C#
public int OSMinorVersion { get; set; }

This is the Minor Version number. See OSValues for possible values.

C#
public int BuildNumber { get; set; }

This is the Build number. I couldn't find a list of possible values, but this will change with each service pack. I have started an associated enum called OSBuildNumber, but it only has three values so far. (I only have access to three systems.)

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

Note: I would appreciate it if you have access to a different version and if you would email me with the build number of your system. You can get the build number by running the demo OSVersionDemo. I will then update this article with the appropriate values. I would especially like the build number of NT4 SP6, as this is the first operating system that supports the extended information.

C#
public string OSCSDVersion { get; set; }

This is a string, such as "Service Pack 3", that indicates the latest service pack installed on the system. If no service pack has been installed, the string is empty.

Extended Properties

These properties provide direct access to the underlying fields, but are only available for operating systems including or later than NT4 SP6. You can check whether these properties are available by getting the value of the ExtendedPropertiesAreSet property. If you try to access these properties when ExtendedPropertiesAreSet is false, they will throw an exception. They are:

C#
public Commmon.OSSuites OSSuiteFlags { get; set; }

This property is a bit-wise combination of the OSSuites enum:

C#
[ 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,
}

As you can see, these values mostly apply to server systems.

C#
<a name=""OSProductType""></a>    public Commmon.OSProductType OSProductType { get; set; }

This property is an OSProductType:

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

These values differentiate between the different types of an operating system family.

C#
public Int16 OSServicePackMajor { get; set; }

This property is the Major Version number of the latest service pack that has been applied. If no service pack has been installed, the value is zero.

C#
public Int16 OSServicePackMinor { get; set; }

This property is the Minor Version number of the latest service pack that has been applied. If no service pack has been installed, the value is zero.

C#
public byte OSReserved { get; set; }

This property is reserved for future use.

Underlying Properties

These properties give access to the underlying values in the OSVERSIONINFO or OSVERSIONINFOEX structures. They are provided for compatibility with the System.OperatingSystem class.

C#
public int Platform { get; }

This property is the operating system PlatformId. See OSPlatformId.

C#
public int SuiteMask { get; }

This property is a bit flag value that identifies the product suites available on the system. See OSSuiteFlags.

C#
public byte ProductType { get; }

This property provides additional information about the system. See OSProductType.

Calculated Properties

These properties are calculated from the underlying fields (and so cannot be set).

C#
public System.Version Version { get; }

This property is provided for compatibility with the System.OperatingSystem class.

C#
public Common.OSVersion OSVersion { get; }

This property is very useful. It calculates the operating system version from the OSPlatformId, OSMajorVersion and OSMinorVersion. See OSValues for details. It returns a Common.OSVersion, which is an enum:

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

This enum specifies one of the 15 Windows operating system versions.

String Properties

These properties return string representations of some of the properties:

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

The Object.ToString() method is also overridden and provides a full description of the operating system.

Points of Interest

This code is just a wrapper for low-level methods, to provide a useful abstraction of the details. It's not very interesting code, but it does a good job - at least I think so. :)

The hardest part was finding enough information to differentiate between the versions. I've done this now, so you don't have to. :)

OSValues

Out of interest, here are the PlatformId, Major and Minor Version Numbers of the 15 32-bit and 64-bit Windows operating systems:

+------------+------------+-------+-------+---------+
| 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 |
+------------+------------+-------+-------+---------+

This is the data that has been encapsulated by the OSVersionInfo class. Using this class is easier and less error-prone than coding these values across your solution.

References

The information required to decipher the operating system version numbers is spread throughout MSDN. Here are some of the sources I used:

Platform SDK

Knowledge Base

.NET Framework

As you can see, Microsoft didn't make this easy. :)

As always, Lutz Roeder's Reflector [^] and the PInvoke.net [^] Wiki proved very useful.

History

  • 29th March, 2010: Version 3 - supports 2008, 2008 R2 and Win7
  • 3rd January, 2008: Version 2 - supports XP x64 and Vista
  • 25th May, 2005: Version 1 - supports up to 2003

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
I discovered C# and .NET 1.0 Beta 1 in late 2000 and loved them immediately.
I have been writing software professionally in C# ever since

In real life, I have spent 3 years travelling abroad,
I have held a UK Private Pilots Licence for 20 years,
and I am a PADI Divemaster.

I now live near idyllic Bournemouth in England.

I can work 'virtually' anywhere!

Comments and Discussions

 
QuestionVersion of Remote Machine? Pin
MOT76-Jan-11 9:24
MOT76-Jan-11 9:24 
Is it possible to get this information from a remote machine?

What fields should I populate to use this with WMI?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.