Much to my surprise I discovered that the full build number for a Windows OS is not stored in WMI in the usual Win32_OperatingSystem class.
In Windows 10 at least, the full build number containing the “UBR”, or essentially the CU patch level of the build, is a useful piece of information.
Open Settings > System > About on a Windows 10 box, and you’ll find the OS Build value, in my case 15063.183
If I run the usual WMI query to get the build number I just get 15063:
Same if I query the environment:
To find the full number I have to query the registry in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion branch.
So I put together a PowerShell script that can be used to get the Windows version for a local or remote computer (or group of computers) which includes the Edition, Version and full OS Build values.
Query the local system like this:
Get-WindowsVersion
Or query remote computers:
Get-WindowsVersion -ComputerName PC001
Get-WindowsVersion -ComputerName @("PC001","PC002","SRV001","SRV002")
Result:
The script
[CmdletBinding()] | |
Param | |
( | |
[Parameter(Mandatory=$false, | |
ValueFromPipelineByPropertyName=$true, | |
ValueFromPipeline=$true | |
)] | |
[string[]]$ComputerName = $env:COMPUTERNAME | |
) | |
Begin | |
{ | |
$Table = New-Object System.Data.DataTable | |
$Table.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build")) | |
} | |
Process | |
{ | |
Foreach ($Computer in $ComputerName) | |
{ | |
$Code = { | |
$ProductName = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ProductName).ProductName | |
Try | |
{ | |
$Version = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ReleaseID –ErrorAction Stop).ReleaseID | |
} | |
Catch | |
{ | |
$Version = "N/A" | |
} | |
$CurrentBuild = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name CurrentBuild).CurrentBuild | |
$UBR = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name UBR).UBR | |
$OSVersion = $CurrentBuild + "." + $UBR | |
$TempTable = New-Object System.Data.DataTable | |
$TempTable.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build")) | |
[void]$TempTable.Rows.Add($env:COMPUTERNAME,$ProductName,$Version,$OSVersion) | |
Return $TempTable | |
} | |
If ($Computer -eq $env:COMPUTERNAME) | |
{ | |
$Result = Invoke-Command –ScriptBlock $Code | |
[void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build') | |
} | |
Else | |
{ | |
Try | |
{ | |
$Result = Invoke-Command –ComputerName $Computer –ScriptBlock $Code –ErrorAction Stop | |
[void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build') | |
} | |
Catch | |
{ | |
$_ | |
} | |
} | |
} | |
} | |
End | |
{ | |
Return $Table | |
} |
Wauw, beside your nice script, this must be the coolest .net class I’ve ever seen System.Data.DataTable Many Thanks for that, nice and easy way to create objects..I guess better than the hashtables everyone knows about to create PCCustomobjects…or which one is in your opinion more a favorite?
Thanks, hashtables are perfectly cool too 🙂 I often query SQL data so I’m in the habit of using the datatable format, but it works quite well for general use too.
What am I missing here? I can run the script and return the local computers value. But, I can’t seem to figure out how to return remote system values and groups of remote system values.
function Get-WindowsVersion {
^ required on line one for the script to work properly with the command indicated.
Maybe this was implied? I had to ask IRC to get this information. I hope this helps anyone else trying to use the script.
You can also call this like: ‘.\Get Computer Build Number.ps1’ -ComputerName ‘Name’ | Export-csv ‘path’
or: ‘.\Get Computer Build Number.ps1’ -ComputerName @(‘Name’, ‘Name1’) | Export-csv ‘path’
Ah, makes sense, cool thank you.
Hey Paul. I’m trying the same thing you are, but cant seem to figure out what you mean above. Can you post the modified script for remote users?
Thanks.
Thanks, how can we modify it for text inputs?
Hey, great work! This came up as I was looking into how to get the full build number 🙂
excellent solution, thanks a lot.
Excellent script that saved me a lot of work. Thank you Trevor for sharing.
And thank you Paul R. for your notice
OK, I can get the script to work on my local machine, but how do you make this script get the info for 500 machines? I have a txt file with the PC names, how can I make it read each name in the txt file and display the Windows Version?
Thanks,
If your file is just computer names: Get-Content .\Yourfile.txt | .\NameOfTheScript.ps1
If your file is a CSV, name column header “ComputerName” then: Import-Csv .\YourFile.csv | .\NameOfTheScript.ps1
Either of those should work since the has “ValueFromPipelineByPropertyName = $true” which handles the CSV with proper column name and “ValueFromPipeline = $true” takes any string input from pipeline.