Introduction
To retrieve information about the operating system, Windows provides the following API:
- GetVersion, retrieves information about the current operating system in a OSVERSIONINFO structure. The information in OSVERSIONINFO includes major and minor version numbers, a build number, a platform identifier, and descriptive text about the operating system. This function has been superseded by
- GetVersionEx, retrieves information about the current operating system in a OSVERSIONINFOEX structure. The information in OSVERSIONINFOEX includes major and minor version numbers, a build number, a platform identifier, and information about product suites and the latest Service Pack installed on the system. This function returns correct information only if the process does not run under a compatibility layer.
- GetProductInfo, retrieves the product type for the operating system on the local computer, and maps the type to the product types supported by the specified operating system.
OS Version
Operating systems are grouped in two platforms:
- Win32: includes Windows 95, Windows 98, and Windows Millennium;
- WinNT: includes Windows NT, Windows 2000, Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008 and Windows 7.
Win32 systems have the Major Version equal to 4, and the difference is made by the Minor Version: 0 for Win95, 10 for Win98, and 90 for WinMe. Win95 also comes in an OSR2 release, and you must use the CSD Version to determine the actual edition. If it is 'C' or 'B', it is a OSR2 edition. For Win98, if the CSD Version is 'A', Second Edition is present.
WinNT systems are first differentiated by the major version:
The minor version is used, for instance, to differentiate among Windows 2000 (0), Windows XP(1), and Windows Server 2003 (2), Windows Home Server (2), etc. Some system have the same value for the minor version (Windows Vista and Windows Server 2008, or Windows 7 and Windows Server 2008 R2). In this case additional information is needed to differentiate between them. The product type groups the operating systems in servers (3), workstations (2), and domain controllers (1). Another flag that differentiate between editions is the suite mask. It can indicate an enterprise edition (0x0002), data center edition (0x0080), a personal/home edition (0x0200), or a web edition (0x0400). A better, visual, grouping of the operating systems is shown in the following images. For Windows NT: For Windows Vista, Windows 7 and Windows Server 2008: In addition to that, on Windows Vista and Windows Server 2008 a new function is available in kernel32.dll, called GetProductInfo(). It retrieves the product type for the operating system on the local computer, and maps the type to the product types supported by the specified operating system. You have to supply the major and minor version of the OS and the major and minor version of the service pack; then it returns a value that can indicate an unknown product, and unlicensed product or a specific edition such as business, ultimate, enterprise, enterprise server, and so on. For more about the function and possible value, see MSDN.

System Info Types
Structure OSVERSIONINFOEX
This provides the following information:
Structure SYSTEM_INFO
This contains information about the system, such as arhitecture and type of processors. Of particular interest is the wProcessorArchitecture attribute that specifies, as the name implies, the processor architecture. According to MSDN, it can be one of the following: However, winnt.h lists several more constants for the architecture:
#define PROCESSOR_ARCHITECTURE_INTEL 0
#define PROCESSOR_ARCHITECTURE_MIPS 1
#define PROCESSOR_ARCHITECTURE_ALPHA 2
#define PROCESSOR_ARCHITECTURE_PPC 3
#define PROCESSOR_ARCHITECTURE_SHX 4
#define PROCESSOR_ARCHITECTURE_ARM 5
#define PROCESSOR_ARCHITECTURE_IA64 6
#define PROCESSOR_ARCHITECTURE_ALPHA64 7
#define PROCESSOR_ARCHITECTURE_MSIL 8
#define PROCESSOR_ARCHITECTURE_AMD64 9
#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
For more, check MSDN.
Class Environment
.NET framework has a static class in the System namespace called Environment. This class provides information about the current environment and platform. It has a static property called OSVersion that contains the current platform identifier and version number.
Retrieving OS Info in C#
To retrieve the Windows version and edition in C#, we need first to define some Windows constants, structures and the functions we will call (GetVersionEx, GetProductInfo, GetSystemInfo, GetSystemMetrics).
public static class Win32Api
{
public const byte VER_NT_WORKSTATION = 1;
public const byte VER_NT_DOMAIN_CONTROLLER = 2;
public const byte VER_NT_SERVER = 3;
public const ushort VER_SUITE_SMALLBUSINESS = 1;
public const ushort VER_SUITE_ENTERPRISE = 2;
public const ushort VER_SUITE_TERMINAL = 16;
public const ushort VER_SUITE_DATACENTER = 128;
public const ushort VER_SUITE_SINGLEUSERTS = 256;
public const ushort VER_SUITE_PERSONAL = 512;
public const ushort VER_SUITE_BLADE = 1024;
public const ushort VER_SUITE_WH_SERVER = 32768;
public const uint PRODUCT_UNDEFINED = 0x00000000;
public const uint PRODUCT_ULTIMATE = 0x00000001;
public const uint PRODUCT_HOME_BASIC = 0x00000002;
public const uint PRODUCT_HOME_PREMIUM = 0x00000003;
public const uint PRODUCT_ENTERPRISE = 0x00000004;
public const uint PRODUCT_HOME_BASIC_N = 0x00000005;
public const uint PRODUCT_BUSINESS = 0x00000006;
public const uint PRODUCT_STANDARD_SERVER = 0x00000007;
public const uint PRODUCT_DATACENTER_SERVER = 0x00000008;
public const uint PRODUCT_SMALLBUSINESS_SERVER = 0x00000009;
public const uint PRODUCT_ENTERPRISE_SERVER = 0x0000000A;
public const uint PRODUCT_STARTER = 0x0000000B;
public const uint PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C;
public const uint PRODUCT_STANDARD_SERVER_CORE = 0x0000000D;
public const uint PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E;
public const uint PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F;
public const uint PRODUCT_BUSINESS_N = 0x00000010;
public const uint PRODUCT_WEB_SERVER = 0x00000011;
public const uint PRODUCT_CLUSTER_SERVER = 0x00000012;
public const uint PRODUCT_HOME_SERVER = 0x00000013;
public const uint PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014;
public const uint PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015;
public const uint PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016;
public const uint PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017;
public const uint PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018;
public const uint PRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019;
public const uint PRODUCT_HOME_PREMIUM_N = 0x0000001A;
public const uint PRODUCT_ENTERPRISE_N = 0x0000001B;
public const uint PRODUCT_ULTIMATE_N = 0x0000001C;
public const uint PRODUCT_WEB_SERVER_CORE = 0x0000001D;
public const uint PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E;
public const uint PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F;
public const uint PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020;
public const uint PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023;
public const uint PRODUCT_STANDARD_SERVER_V = 0x00000024;
public const uint PRODUCT_ENTERPRISE_SERVER_V = 0x00000026;
public const uint PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028;
public const uint PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029;
public const uint PRODUCT_HYPERV = 0x0000002A;
public const ushort PROCESSOR_ARCHITECTURE_INTEL = 0;
public const ushort PROCESSOR_ARCHITECTURE_IA64 = 6;
public const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9;
public const ushort PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;
public const int SM_SERVERR2 = 89;
[StructLayout(LayoutKind.Sequential)]
public struct OSVERSIONINFOEX
{
public uint dwOSVersionInfoSize;
public uint dwMajorVersion;
public uint dwMinorVersion;
public uint dwBuildNumber;
public uint dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion;
public ushort wServicePackMajor;
public ushort wServicePackMinor;
public ushort wSuiteMask;
public byte wProductType;
public byte wReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
public uint wProcessorArchitecture;
public uint wReserved;
public uint dwPageSize;
public uint lpMinimumApplicationAddress;
public uint lpMaximumApplicationAddress;
public uint dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public uint dwProcessorLevel;
public uint dwProcessorRevision;
}
[DllImport("Kernel32.dll")]
internal static extern bool GetProductInfo(
uint osMajorVersion,
uint osMinorVersion,
uint spMajorVersion,
uint spMinorVersion,
out uint edition);
[DllImport("kernel32.dll")]
internal static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);
[DllImport("kernel32.dll")]
internal static extern void GetSystemInfo(ref SYSTEM_INFO pSI);
[DllImport("user32.dll")]
internal static extern int GetSystemMetrics(int nIndex);
}
Next, we can define some enumerations for possible Windows versions and editions.
public enum WindowsVersion
{
Unknown,
Windows95,
Windows95OSR2,
Windows98,
Windows98SE,
WindowsMillennium,
WindowsNT351,
WindowsNT40,
WindowsNT40Server,
Windows2000,
WindowsXP,
WindowsXPProfessionalx64,
WindowsHomeServer,
WindowsServer2003,
WindowsServer2003R2,
WindowsVista,
WindowsServer2008,
WindowsServer2008R2,
Windows7,
}
public enum WindowsEdition
{
Unknown,
Workstation,
EnterpriseServer,
StandardServer,
Home,
Professional,
Server,
DatacenterServer,
AdvancedServer,
WebEdition,
Business,
Business_N,
HPCEdition,
DatacenterServer_CoreInstallation,
Enterprise,
Enterprise_N,
EnterpriseServer_CoreInstallation,
EnterpriseServer_WithoutHyperV_CoreInstallation,
EnterpriseServer_ForItaniumBasedSystems,
EnterpriseServer_WithoutHyperV,
HomeBasic,
HomeBasic_N,
HomePremium,
HomePremium_N,
HyperVServer,
EssentialBusinessManagementServer,
EssentialBusinessMessagingServer,
EssentialBusinessSecurityServer,
EssentialServerSolutions,
EssentialServerSolutions_WithoutHyperV,
SmallBusinessServer,
StandardServer_CoreInstallation,
StandardServer_WithoutHyperV_CoreInstallation,
StandardServer_WithoutHyperV,
Starter,
EnterpriseStorageServer,
ExpressStorageServer,
StandardStorageServer,
WorkgroupStorageServer,
Ultimate,
Ultimate_N,
WebServer,
WebServer_CoreInstallation
}
}
With this defined I have created a class called SystemInfo that is using the Environment class to retrieve information such as major and minor numbers, build or version string. For information about the version, edition and service pack I have used the Windows API functions enumerated earlier. This is how this class looks:
public static class SystemInfo
{
public static int MajorVersion
{
get { return Environment.OSVersion.Version.Major; }
}
public static int MinorVersion
{
get { return Environment.OSVersion.Version.Minor; }
}
public static int MajorRevision
{
get { return Environment.OSVersion.Version.MajorRevision; }
}
public static int MinorRevision
{
get { return Environment.OSVersion.Version.MinorRevision; }
}
public static int Revision
{
get { return Environment.OSVersion.Version.Revision; }
}
public static int Build
{
get { return Environment.OSVersion.Version.Build; }
}
public static string VersionString
{
get { return Environment.OSVersion.Version.ToString(); }
}
public static string ServicePack
{
get
{
string servicePack = String.Empty;
Win32Api.OSVERSIONINFOEX osVersionInfo = new Win32Api.OSVERSIONINFOEX();
osVersionInfo.dwOSVersionInfoSize = (uint)Marshal.SizeOf(typeof(Win32Api.OSVERSIONINFOEX));
if (Win32Api.GetVersionEx(ref osVersionInfo))
{
servicePack = osVersionInfo.szCSDVersion;
}
return servicePack;
}
}
public static WindowsVersion Version
{
get
{
WindowsVersion version = WindowsVersion.Unknown;
Win32Api.OSVERSIONINFOEX osVersionInfo = new Win32Api.OSVERSIONINFOEX();
osVersionInfo.dwOSVersionInfoSize = (uint)Marshal.SizeOf(typeof(Win32Api.OSVERSIONINFOEX));
Win32Api.SYSTEM_INFO systemInfo = new Win32Api.SYSTEM_INFO();
Win32Api.GetSystemInfo(ref systemInfo);
if (Win32Api.GetVersionEx(ref osVersionInfo))
{
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32Windows:
{
switch (osVersionInfo.dwMajorVersion)
{
case 4:
{
switch (osVersionInfo.dwMinorVersion)
{
case 0:
if (osVersionInfo.szCSDVersion == "B" ||
osVersionInfo.szCSDVersion == "C")
version = WindowsVersion.Windows95OSR2;
else
version = WindowsVersion.Windows95;
break;
case 10:
if (osVersionInfo.szCSDVersion == "A")
version = WindowsVersion.Windows98SE;
else
version = WindowsVersion.Windows98;
break;
case 90:
version = WindowsVersion.WindowsMillennium;
break;
}
}
break;
}
}
break;
case PlatformID.Win32NT:
{
switch (osVersionInfo.dwMajorVersion)
{
case 3:
version = WindowsVersion.WindowsNT351;
break;
case 4:
switch (osVersionInfo.wProductType)
{
case 1:
version = WindowsVersion.WindowsNT40;
break;
case 3:
version = WindowsVersion.WindowsNT40Server;
break;
}
break;
case 5:
{
switch (osVersionInfo.dwMinorVersion)
{
case 0:
version = WindowsVersion.Windows2000;
break;
case 1:
version = WindowsVersion.WindowsXP;
break;
case 2:
{
if (osVersionInfo.wSuiteMask == Win32Api.VER_SUITE_WH_SERVER)
{
version = WindowsVersion.WindowsHomeServer;
}
else if (osVersionInfo.wProductType == Win32Api.VER_NT_WORKSTATION &&
systemInfo.wProcessorArchitecture == Win32Api.PROCESSOR_ARCHITECTURE_AMD64)
{
version = WindowsVersion.WindowsXPProfessionalx64;
}
else
{
version = Win32Api.GetSystemMetrics(Win32Api.SM_SERVERR2) == 0 ?
WindowsVersion.WindowsServer2003 :
WindowsVersion.WindowsServer2003R2;
}
}
break;
}
}
break;
case 6:
{
switch (osVersionInfo.dwMinorVersion)
{
case 0:
{
version = osVersionInfo.wProductType == Win32Api.VER_NT_WORKSTATION ?
WindowsVersion.WindowsVista :
WindowsVersion.WindowsServer2008;
}
break;
case 1:
{
version = osVersionInfo.wProductType == Win32Api.VER_NT_WORKSTATION ?
WindowsVersion.Windows7 :
WindowsVersion.WindowsServer2008R2;
}
break;
}
}
break;
}
}
break;
}
}
return version;
}
}
public static WindowsEdition Edition
{
get
{
WindowsEdition edition = WindowsEdition.Unknown;
Win32Api.OSVERSIONINFOEX osVersionInfo = new Win32Api.OSVERSIONINFOEX();
osVersionInfo.dwOSVersionInfoSize = (uint)Marshal.SizeOf(typeof(Win32Api.OSVERSIONINFOEX));
if (Win32Api.GetVersionEx(ref osVersionInfo))
{
switch(osVersionInfo.dwMajorVersion)
{
case 4:
{
switch(osVersionInfo.wProductType)
{
case Win32Api.VER_NT_WORKSTATION:
edition = WindowsEdition.Workstation;
break;
case Win32Api.VER_NT_SERVER:
edition = (osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_ENTERPRISE) != 0 ?
WindowsEdition.EnterpriseServer :
WindowsEdition.StandardServer;
break;
}
}
break;
case 5:
{
switch (osVersionInfo.wProductType)
{
case Win32Api.VER_NT_WORKSTATION:
{
edition = (osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_PERSONAL) != 0 ?
WindowsEdition.Home :
WindowsEdition.Professional;
}
break;
case Win32Api.VER_NT_SERVER:
{
switch(osVersionInfo.dwMinorVersion)
{
case 0:
{
if ((osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_DATACENTER) != 0)
{
edition = WindowsEdition.DatacenterServer;
}
else if ((osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_ENTERPRISE) != 0)
{
edition = WindowsEdition.AdvancedServer;
}
else
{
edition = WindowsEdition.Server;
}
}
break;
default:
{
if ((osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_DATACENTER) != 0)
{
edition = WindowsEdition.DatacenterServer;
}
else if ((osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_ENTERPRISE) != 0)
{
edition = WindowsEdition.EnterpriseServer;
}
else if ((osVersionInfo.wSuiteMask & Win32Api.VER_SUITE_BLADE) != 0)
{
edition = WindowsEdition.WebEdition;
}
else
{
edition = WindowsEdition.StandardServer;
}
}
break;
}
}
break;
}
}
break;
case 6:
{
uint ed;
if (Win32Api.GetProductInfo(
osVersionInfo.dwMajorVersion,
osVersionInfo.dwMinorVersion,
osVersionInfo.wServicePackMajor,
osVersionInfo.wServicePackMinor,
out ed))
{
switch (ed)
{
case Win32Api.PRODUCT_BUSINESS:
edition = WindowsEdition.Business;
break;
case Win32Api.PRODUCT_BUSINESS_N:
edition = WindowsEdition.Business_N;
break;
case Win32Api.PRODUCT_CLUSTER_SERVER:
edition = WindowsEdition.HPCEdition;
break;
case Win32Api.PRODUCT_DATACENTER_SERVER:
edition = WindowsEdition.DatacenterServer;
break;
case Win32Api.PRODUCT_DATACENTER_SERVER_CORE:
edition = WindowsEdition.DatacenterServer_CoreInstallation;
break;
case Win32Api.PRODUCT_ENTERPRISE:
edition = WindowsEdition.Enterprise;
break;
case Win32Api.PRODUCT_ENTERPRISE_N:
edition = WindowsEdition.Enterprise_N;
break;
case Win32Api.PRODUCT_ENTERPRISE_SERVER:
edition = WindowsEdition.EnterpriseServer;
break;
case Win32Api.PRODUCT_ENTERPRISE_SERVER_CORE:
edition = WindowsEdition.EnterpriseServer_CoreInstallation;
break;
case Win32Api.PRODUCT_ENTERPRISE_SERVER_CORE_V:
edition = WindowsEdition.EnterpriseServer_WithoutHyperV_CoreInstallation;
break;
case Win32Api.PRODUCT_ENTERPRISE_SERVER_IA64:
edition = WindowsEdition.EnterpriseServer_ForItaniumBasedSystems;
break;
case Win32Api.PRODUCT_ENTERPRISE_SERVER_V:
edition = WindowsEdition.EnterpriseServer_WithoutHyperV;
break;
case Win32Api.PRODUCT_HOME_BASIC:
edition = WindowsEdition.HomeBasic;
break;
case Win32Api.PRODUCT_HOME_BASIC_N:
edition = WindowsEdition.HomeBasic_N;
break;
case Win32Api.PRODUCT_HOME_PREMIUM:
edition = WindowsEdition.HomePremium;
break;
case Win32Api.PRODUCT_HOME_PREMIUM_N:
edition = WindowsEdition.HomePremium_N;
break;
case Win32Api.PRODUCT_HYPERV:
edition = WindowsEdition.HyperVServer;
break;
case Win32Api.PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
edition = WindowsEdition.EssentialBusinessManagementServer;
break;
case Win32Api.PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
edition = WindowsEdition.EssentialBusinessMessagingServer;
break;
case Win32Api.PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
edition = WindowsEdition.EssentialBusinessSecurityServer;
break;
case Win32Api.PRODUCT_SERVER_FOR_SMALLBUSINESS:
edition = WindowsEdition.EssentialServerSolutions;
break;
case Win32Api.PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
edition = WindowsEdition.EssentialServerSolutions_WithoutHyperV;
break;
case Win32Api.PRODUCT_SMALLBUSINESS_SERVER:
edition = WindowsEdition.SmallBusinessServer;
break;
case Win32Api.PRODUCT_STANDARD_SERVER:
edition = WindowsEdition.StandardServer;
break;
case Win32Api.PRODUCT_STANDARD_SERVER_CORE:
edition = WindowsEdition.StandardServer_CoreInstallation;
break;
case Win32Api.PRODUCT_STANDARD_SERVER_CORE_V:
edition = WindowsEdition.StandardServer_WithoutHyperV_CoreInstallation;
break;
case Win32Api.PRODUCT_STANDARD_SERVER_V:
edition = WindowsEdition.StandardServer_WithoutHyperV;
break;
case Win32Api.PRODUCT_STARTER:
edition = WindowsEdition.Starter;
break;
case Win32Api.PRODUCT_STORAGE_ENTERPRISE_SERVER:
edition = WindowsEdition.EnterpriseStorageServer;
break;
case Win32Api.PRODUCT_STORAGE_EXPRESS_SERVER:
edition = WindowsEdition.ExpressStorageServer;
break;
case Win32Api.PRODUCT_STORAGE_STANDARD_SERVER:
edition = WindowsEdition.StandardStorageServer;
break;
case Win32Api.PRODUCT_STORAGE_WORKGROUP_SERVER:
edition = WindowsEdition.WorkgroupStorageServer;
break;
case Win32Api.PRODUCT_UNDEFINED:
edition = WindowsEdition.Unknown;
break;
case Win32Api.PRODUCT_ULTIMATE:
edition = WindowsEdition.Ultimate;
break;
case Win32Api.PRODUCT_ULTIMATE_N:
edition = WindowsEdition.Ultimate_N;
break;
case Win32Api.PRODUCT_WEB_SERVER:
edition = WindowsEdition.WebServer;
break;
case Win32Api.PRODUCT_WEB_SERVER_CORE:
edition = WindowsEdition.WebServer_CoreInstallation;
break;
}
}
}
break;
}
}
return edition;
}
}
}
The following code shows how one can use this SystemInfo class:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Version: {0}", SystemInfo.Version);
Console.WriteLine("Edition: {0}", SystemInfo.Edition);
Console.WriteLine("Major version: {0}", SystemInfo.MajorVersion);
Console.WriteLine("Minor version: {0}", SystemInfo.MinorVersion);
Console.WriteLine("Major revision: {0}", SystemInfo.MajorRevision);
Console.WriteLine("Minor revision: {0}", SystemInfo.MinorRevision);
Console.WriteLine("Revision: {0}", SystemInfo.Revision);
Console.WriteLine("Build: {0}", SystemInfo.Build);
Console.WriteLine("Version: {0}", SystemInfo.VersionString);
Console.WriteLine("Service Pack: {0}", SystemInfo.ServicePack);
}
}
The output on my machine running Windows XP Professional with SP3 is:
Version: WindowsXP
Edition: Professional
Major version: 5
Minor version: 1
Major revision: 3
Minor revision: 0
Revision: 196608
Build: 2600
Version: 5.1.2600.196608
Service Pack: Service Pack 3





