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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | using System; using System.Management; using System.Text.RegularExpressions; /// <summary> /// Gets Operating System Name, Service Pack, and Architecture using WMI with the legacy methods as a fallback /// </summary> /// <returns>String containing the name of the operating system followed by its service pack (if any) and architecture</returns> 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"; } |
Legacy code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | /// <summary> /// Gets Operating System Name using .Net's Environment class. /// </summary> /// <returns>String containing the name of the operating system followed by its service pack (if any)</returns> 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; } /// <summary> /// Gets the installed Operating System Service Pack using .Net's Environment class. /// </summary> /// <returns>String containing the operating system's installed service pack (if any)</returns> 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 ""; } /// <summary> /// 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. /// </summary> /// <returns>Int containing 32 or 64 representing the number of bits in the OS Architecture</returns> private int getOSArchitectureLegacy() { string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa,0,"x86",0,3,true) == 0) ? 32 : 64); } |
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.
- 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.
- 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.
Possibly Related posts:


Pingback: C# Detect Windows OS Version – Part 1 | AndrewEnsley.com
Pingback: 一键安装IIS的点点滴滴——For所有Microsoft的操作系统(下) at 广州华山文化传播