C# Detect Windows OS Version – Part 2 (WMI)

Recap

In case you missed Part 1, I briefly summarized 4 different strategies for programmatically determining the current Operating System in C#.  The code I posted there utilizes the System.Environment class.  It works great and is sufficient for most uses, but sometimes you want need to know everything about the OS, including the edition (i.e. “XP Pro” vs. “XP Home”).

Summary

For that, Microsoft gives us the lovely Windows Management Instrumentation (WMI) Interface.  You can do a lot of really powerful and interesting things with WMI and WQL, but for this purpose, all we care about is getting some information from it.

The Code

Not all Windows versions support WMI, so we always have to fall back on the Environment class code from Part 1.  Without wasting your time, let’s get straight to the code.

WMI

[cc lang=’csharp’]
using System;
using System.Management;
using System.Text.RegularExpressions;

///

/// Gets Operating System Name, Service Pack, and Architecture using WMI with the legacy methods as a fallback
///

/// String containing the name of the operating system followed by its service pack (if any) and architecture
private string getOSInfo()
{
ManagementObjectSearcher objMOS = new ManagementObjectSearcher(“SELECT * FROM Win32_OperatingSystem”);

//Variables to hold our return value
string os = “”;
int OSArch = 0;

try
{
foreach (ManagementObject objManagement in objMOS.Get())
{
// Get OS version from WMI – This also gives us the edition
object osCaption = objManagement.GetPropertyValue(“Caption”);
if (osCaption != null)
{
// Remove all non-alphanumeric characters so that only letters, numbers, and spaces are left.
string osC = Regex.Replace(osCaption.ToString(),”[^A-Za-z0-9 ]”,””);
//string osC = osCaption.ToString();
// If the OS starts with “Microsoft,” remove it. We know that already
if (osC.StartsWith(“Microsoft”))
{
osC = osC.Substring(9);
}
// If the OS now starts with “Windows,” again… useless. Remove it.
if (osC.Trim().StartsWith(“Windows”))
{
osC = osC.Trim().Substring(7);
}
// Remove any remaining beginning or ending spaces.
os = osC.Trim();
// Only proceed if we actually have an OS version – service pack is useless without the OS version.
if(!String.IsNullOrEmpty(os))
{
object osSP = null;
try
{
// Get OS service pack from WMI
osSP = objManagement.GetPropertyValue(“ServicePackMajorVersion”);
if (osSP != null && osSP.ToString() != “0”)
{
os += ” Service Pack ” + osSP.ToString();
}
else
{
// Service Pack not found. Try built-in Environment class.
os += getOSServicePackLegacy();
}
}
catch (Exception)
{
// There was a problem getting the service pack from WMI. Try built-in Environment class.
os += getOSServicePackLegacy();
}
}
object osA = null;
try
{
// Get OS architecture from WMI
osA = objManagement.GetPropertyValue(“OSArchitecture”);
if (osA != null)
{
string osAString = osA.ToString();
// If “64” is anywhere in there, it’s a 64-bit architectore.
OSArch = (osAString.Contains(“64”) ? 64 : 32);
}
}
catch (Exception)
{
}
}
}
}
catch (Exception)
{
}
// If WMI couldn’t tell us the OS, use our legacy method.
// We won’t get the exact OS edition, but something is better than nothing.
if (os == “”)
{
os = getOSLegacy();
}
// If WMI couldn’t tell us the architecture, use our legacy method.
if (OSArch == 0)
{
OSArch = getOSArchitectureLegacy();
}
return os + ” ” + OSArch.ToString() + “-bit”;
}
[/cc]

Legacy code

[cc lang=”csharp”]
///

/// Gets Operating System Name using .Net’s Environment class.
///

/// String containing the name of the operating system followed by its service pack (if any)
private string getOSLegacy()
{
//Get Operating system information.
OperatingSystem os = Environment.OSVersion;
//Get version information about the os.
Version vs = os.Version;

//Variable to hold our return value
string operatingSystem = “”;

if (os.Platform == PlatformID.Win32Windows)
{
//This is a pre-NT version of Windows
switch (vs.Minor)
{
case 0:
operatingSystem = “95”;
break;
case 10:
if (vs.Revision.ToString() == “2222A”)
operatingSystem = “98SE”;
else
operatingSystem = “98”;
break;
case 90:
operatingSystem = “Me”;
break;
default:
break;
}
}
else if(os.Platform == PlatformID.Win32NT)
{
switch (vs.Major)
{
case 3:
operatingSystem = “NT 3.51”;
break;
case 4:
operatingSystem = “NT 4.0”;
break;
case 5:
if (vs.Minor == 0)
{
operatingSystem = “2000”;
}
else
{
operatingSystem = “XP”;
}
break;
case 6:
if (vs.Minor == 0)
{
operatingSystem = “Vista”;
}
else
{
operatingSystem = “7”;
}
break;
default:
break;
}
}
//Make sure we actually got something in our OS check
//We don’t want to just return ” Service Pack 2″
//That information is useless without the OS version.
if(operatingSystem != “”)
{
//Got something. Let’s see if there’s a service pack installed.
operatingSystem += getOSServicePackLegacy();
}
//Return the information we’ve gathered.
return operatingSystem;
}

///

/// Gets the installed Operating System Service Pack using .Net’s Environment class.
///

/// String containing the operating system’s installed service pack (if any)
private string getOSServicePackLegacy()
{
// Get service pack from Environment Class
string sp = Environment.OSVersion.ServicePack;
if (sp != null && sp.ToString() != “” && sp.ToString() != ” “)
{
// If there’s a service pack, return it with a space in front (for formatting)
return ” ” + sp.ToString();
}
// No service pack. Return an empty string
return “”;
}

///

/// Gets Operating System Architecture. This does not tell you if the program in running in
/// 32- or 64-bit mode or if the CPU is 64-bit capable. It tells you whether the actual Operating
/// System is 32- or 64-bit.
///

/// Int containing 32 or 64 representing the number of bits in the OS Architecture
private int getOSArchitectureLegacy()
{
string pa = Environment.GetEnvironmentVariable(“PROCESSOR_ARCHITECTURE”);
return ((String.IsNullOrEmpty(pa) || String.Compare(pa,0,”x86″,0,3,true) == 0) ? 32 : 64);
}
[/cc]

Download this code

Notes

Server Versions

In part 1, the code was completely unaware of Windows Server operating systems.  Fortunately, this WMI approach will tell us about server versions too!  However, you’ll notice that it falls back on the old, non-server-aware code.

If detecting server versions is really important to you, you’ll probably want to separate out the functions so that you can know every case that the WMI code fails to detect the OS.

OS Architecture

Just a reminder: The code that detects OS Architecture (both WMI, and Environment-class-based) tells us about the Operating System version only.

  1. Even though the physical CPU’s architecture may support 64-bit operations, the methods in my code will always return the architecture of the OS. So 32-bit Windows running on a 64-bit capable processor will return 32-bit.
  2. Even though the CPU is 64-bit capable, and the OS architecture is 64-bit, your .Net program could still be running as a 32-bit application. Sometimes, this information is more useful than knowing whether Windows is 32- or 64-bit. To see if your program is actually running in 64-bit mode, check to see if IntPtr.Size == 8. It will be 4 in 32-bit mode and 8 in 64-bit mode.

Andrew

Programmer / Musician / Soccer Player

16 thoughts to “C# Detect Windows OS Version – Part 2 (WMI)”

  1. I am new to this and am having the following error on this line
    ManagementObjectSearcher objMOS = new ManagementObjectSearcher
    “The type or name space ‘ManagementObjectSearcher’ could not be found (are you missing a using directive or an assembly reference?).
    Please help. My current namespace is “CopyToDeskTop” I dont know if this is a problem or not?
    Cheers
    Will

    1. Hi Will,

      Did you copy all the contents of the source file? It sounds like you might be missing part of it, like the using statements:

      using System;
      using System.Management;
      using System.Text.RegularExpressions;

      1. Hi Andrew, Thanks for your quick reply. Yes I have these using statements: using System; using System.Windows.Forms; using System.Management; using System.Text.RegularExpressions;I did copy all of the source file. This is the head of my project
        using System; System;using System.Windows.Forms; System.Windows.Forms;using System.Management; System.Management;using System.Text.RegularExpressions; System.Text.RegularExpressions;namespace CopyToDeskTop{public partial class Form1 : Form CopyToDeskTop{public partial class Form1 : Formpublic partial class Form1 : Form{public Form1(){InitializeComponent();}public Form1(){InitializeComponent();}

        1. Looks like there’s more going on than I could address in a few comments. I’d recommend posting a question on the excellent StackOverflow.com about your problem. If you do, post a link to your question here, and I’ll take a look at it.

  2. Is there any chance I could send you a copy of my solution if I contact you via your contact me page? I struggle to find people who will reply as quick and as straight forward as you.

    1. I still plan on helping you. It’s just easier with the tools that 
       StackOverflow.com has spent so much time and money perfecting. StackOverflow is a great community. If I’m not able to answer your question, I’d be surprised if someone else didn’t within a couple days of you asking.

  3. there is any other method for determining the version of windows 8 and windows 8.1 other than windows WMI(ManagementObjectSearcher) and Environment.OSVersion???

Leave a Reply

Your email address will not be published. Required fields are marked *