Windows Version and Build Number

UPDATED 2022-10-08

Summary

This post demonstrates some techniques for obtaining Windows version information along with advice on what to avoid.

For older Windows operating systems (XP/2003 to 8.1/2012 R2) acquiring the version number was a somewhat simple endeavour.

Starting with Windows 10 and Windows Server 2016, releases consist of two parts, a version number and a build number. A version number may have several build numbers associated with it. For example, Windows 10 with the Anniversary Update is version 1607 which consists of several builds, the last of which to be released was 10.0.14393.1066.

Obtaining the Version Information with PowerShell

XP/2003 to 8.1/2012 R2

My preference is to use the Win32_OperatingSystem WMI class. Normally I’d advocate using the Get-CimInstance cmdlet but since the aim is to target older versions of Windows your success may vary because the cmdlet wasn’t introduced until PowerShell 3.0. I would therefore suggest using Get-WmiObject (which has existed since PowerShell 1.0):

(Get-WmiObject Win32_OperatingSystem).version

I’d advise against using the OSVersion property of the .Net Environment class ([Environment]::OSVersion) because it is liable to return the wrong result on Windows 8.1 if executed from the PowerShell ISE. See Use PowerShell to Find Operating System Version.

Windows 10 / Windows Server 2016 (and beyond?)

Windows Registry

Both the version number and build number can be obtained from the registry. Each element of the build number is stored as a separate value and therefore must be pieced together.

$currentVersion = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
"Version: {0} Build: {1}.{2}.{3}.{4}" -f $currentVersion.ReleaseId,
                                         $currentVersion.CurrentMajorVersionNumber,
                                         $currentVersion.CurrentMinorVersionNumber,
                                         $currentVersion.CurrentBuild,
                                         $currentVersion.UBR

The October 2020 update of Windows 10 had a version number of 20H2, which was the first release to use a new version numbering format representing: "...the half of the calendar year in which the release becomes available in retail and commercial channels", see Windows Experience Blog: What's next for Windows 10 updates. Behind the scenes, this change introduced a new registry value called DisplayVersion, rendering ReleaseId redundant. I've therefore had to update the code to use DisplayVersion if present, otherwise fall back to using ReleaseId (to accommodate versions prior to 20H2).

It wasn't necessary to do so, but I decided to dispense with the variable $currentVersion (featured in the original code above) and use the pipeline instead. Since PowerShell doesn't permit the use an if statement directly in a pipeline, I wrapped the code to the right of the pipe in ForEach-Object.

Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | ForEach-Object {
    "Version: {0}, Build: {1}.{2}.{3}.{4}" -f
        $(If ($_.PSobject.Properties.name.contains('DisplayVersion')) {$_.DisplayVersion} 
        Else {$_.ReleaseId}),
        $_.CurrentMajorVersionNumber,
        $_.CurrentMinorVersionNumber,
        $_.CurrentBuild,
        $_.UBR
}

$PSVersionTable.BuildVersion - DO NOT Use This

DO NOT use $PSVersionTable.BuildVersion.

I was originally under the misapprehension that the BuildVersion property of the PowerShell automatic variable $PSVersionTable referred to that of the Windows OS. I made this mistake because I happened to have access to a Windows 10 computer where $PSVersionTable.BuildVersion.ToString() perfectly matched the OS build number (10.0.16299.461). It wasn’t until I checked another Windows 10 computer that I noticed the values were different (10.0.17134.286 for the OS build number and 10.0.17134.228 for $PSVersionTable.BuildVersion.ToString()).

NB: BuildVersion has since been removed from $PSVersionTable in PowerShell Core, see Remove BuildVersion from $PSVersionTable #3877.

Alternative (but Inadequate) Methods for Obtaining Version and Build Number

Before choosing the registry as the source from which to obtain the version number and build number I looked at and rejected the following alternatives:

Deriving the Windows OS from Version Information

Conventionally Microsoft produce a desktop OS and a server OS from the same code base. Consequently the version information for some desktop and server releases that share the same code base is the same. For example, Windows 7 SP1 and Windows Server 2008 R2 SP1 both return 6.1.7601.65536.

Therefore it’s not possible to derive the Windows OS using only the version information. If you wish to be certain of whether the target OS is desktop or server then in addition to the version information you should also capture the OS name and edition:

(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName

Comments

Leaving comments has been disabled for this post.

Copyright © 2018 - 2022 thecliguy.co.uk
For details, see Licences and Copyright