After reading this, check out Part 2: Using WMI for even more info
I recently needed to programmatically determine the Operating System my software is running on. I was amazed at how difficult it was to find reliable, useful information on this subject. There were bits and pieces here and there, but almost everyone assumed I had some pre-existing knowledge of the process in one manner or another. Hopefully, this little series will save somebody some time in the future.
The thing that makes this so difficult is that there are almost as many different ways to detect the operating system as there are operating systems! It's an unbelievably frustrating experience trying to reinvent this wheel, so I'll try to walk through it here.
There are 4 basic strategies:
- Read and parse information from files in the Windows directory. This is probably the most difficult and least rewarding method. The files are different for each generation of OS and the format is not guaranteed in almost any case.
- Read information from the registry. This method works a little better, but you still have varying locations for the information based on which OS you're dealing with.
- Use Environment variables. Nothing is more reliable. However, it doesn't give you the nitty-gritty detail you might want. For example: There's no way to detect XP Home vs. XP Professional.
- Use WMI to query for information about the OS. This gives you everything you could possibly want all in one shot. Unfortunately, it's not supported in pre-NT versions of Windows (of course, this is becoming less and less of a problem).
I started with number 1. After pulling most of my hair out and wanting to punch my keyboard, I moved on to number 2. That was a dead end too. I could have made it work, but I didn't have the patience. I gave number 3 a try and was very happy... ...until I decided that the specific version of 2000, XP, Vista, and 7 mattered to me. So I finally ended up with a combination of 3 and 4.
For part 1 of this series, I'm going to focus on number 3, a.k.a. The Easy Waytm
The key to everything is the Environment class. It has everything we need in a property called OSVersion. However, the information is a little cryptic (mostly a bunch of numbers), so it takes some work to get a "friendly" value returned.
This first method gives us the Operating system architecture as an integer. The environment variable "PROCESSOR_ARCHITECTURE" is either set to "x86" or doesn't exist on 32-bit versions of Windows. It's always set to something other than "x86" on 64-bit versions of Windows.
string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64);
For something that seems so simple, this can actually be very confusing. There are two important notes about this method:
- Even though the physical CPU's architecture may support 64-bit operations, this environment variable will always return the architecture of the OS. So 32-bit Windows running on a 64-bit capable processor will return 32-bit. It's a bit of a misnomer, but provides the information we really want anyway.
- 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.
Now onto the actual Operating System version. The following code is largely based on what I found on the Microsoft Knowledge Base article: How to determine the Windows version by using Visual C#.
//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
operatingSystem = "95";
if (vs.Revision.ToString() == "2222A")
operatingSystem = "98SE";
operatingSystem = "98";
operatingSystem = "Me";
else if (os.Platform == PlatformID.Win32NT)
operatingSystem = "NT 3.51";
operatingSystem = "NT 4.0";
if (vs.Minor == 0)
operatingSystem = "2000";
operatingSystem = "XP";
if (vs.Minor == 0)
operatingSystem = "Vista";
operatingSystem = "7";
//Make sure we actually got something in our OS check
//We don't want to just return " Service Pack 2" or " 32-bit"
//That information is useless without the OS version.
if (operatingSystem != "")
//Got something. Let's prepend "Windows" and get more info.
operatingSystem = "Windows " + operatingSystem;
//See if there's a service pack installed.
if (os.ServicePack != "")
//Append it to the OS name. i.e. "Windows XP Service Pack 3"
operatingSystem += " " + os.ServicePack;
//Append the OS architecture. i.e. "Windows XP Service Pack 3 32-bit"
operatingSystem += " " + getOSArchitecture().ToString() + "-bit";
//Return the information we've gathered.
Notice that getOSInfo() returns an empty string if it was unable to determine the OS version.
The code should be pretty self-explanatory, and the great thing is that you don't have to reference any special assemblies. Everything is right there in System.