Identifying Windows Version (Part 2)

by Jun 16, 2021

In the previous tip we reported that ReleaseId is deprecated and can no longer be used to correctly identify the current Windows 10 version. Instead, DisplayVersion should be used:

 
PS> (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').DisplayVersion
20H2  
 

However, DisplayVersion, too, is not a dependable way of determining the current Windows 10 version as its purpose originally was to enable the shell to report the current version to the user. It, too, may change in the future.

The only supported safe way of identifying the current Windows 10 version is using an OS class called AnalyticsInfo. This is not trivial though because the class runs asynchronously in WinRT. PowerShell 7 (pwsh.exe) cannot access this class. The built-in Windows PowerShell (powershell.exe) however can create a wrapper and return the information:

# load WinRT and runtime types
[System.Void][Windows.System.Profile.AnalyticsInfo,Windows.System.Profile,ContentType=WindowsRuntime]
Add-Type -AssemblyName 'System.Runtime.WindowsRuntime'

# define call and information to query
[Collections.Generic.List[System.String]]$names = 'DeviceFamily',
                                                  'OSVersionFull',
                                                  'FlightRing', 
                                                  'App', 
                                                  'AppVer'

$task = [Windows.System.Profile.AnalyticsInfo]::GetSystemPropertiesAsync($names)

# use reflection to find method definition
$definition = [System.WindowsRuntimeSystemExtensions].GetMethods().Where{
    $_.Name -eq 'AsTask' -and 
    $_.GetParameters().Count -eq 1 -and 
    $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' 
}

# create generic method
$Method = $definition.MakeGenericMethod( [System.Collections.Generic.IReadOnlyDictionary[System.String,System.String]] )

# call async method and wait for completion
$task = $Method.Invoke.Invoke($null, $task)
$null = $task.Wait(-1)

# emit output
$task.Result

The result looks similar to this:

 
Key           Value                                         
---           -----                                         
OSVersionFull 10.0.19042.985.amd64fre.vb_release.191206-1406
FlightRing    Retail                                        
App           powershell_ise.exe                            
AppVer        10.0.19041.1                                  
DeviceFamily  Windows.Desktop   
 

OSVersionFull returns the full details about the current Windows version.

Note that the method called in the example above can retrieve a lot more details. $names lists the attribute names to query. Unfortunately, there is no way to discover the available attribute names as 3rd party can add potentially endless additional information. The five attributes used in this example are the only ones guaranteed.


Twitter This Tip! ReTweet this Tip!