I want to query the operating system name, and will receive results like this:
Microsoft Windows Server 2022 Standard
or Microsoft Windows 11 Enterprise
.
I would like to correlate this with arbitrary values like: SVR2022
and WIN11
I tried using a hash table to do so like this:
$Version = @{
'Windows 10' = 'WIN10'
'Windows 11' = 'WIN11'
'Server 2022' = 'SVR2022'
'Server 2019' = 'SVR2019'
'Server 2016' = 'SVR2016'
'Server 2012' = 'SVR2012'
'Server 2008' = 'SVR2008'
}
# Collect info
$os = (Get-WmiObject Win32_OperatingSystem)
# Identify OS Version
$wsusVersion = $Version[($Version.Keys | Where-Object $os.Caption -like "*$($_)*")]
This returns a collection with all values in it because I believe $_
is $null
.
I've tried a number of different combinations of code, but am having trouble figuring out the most concise and correct way to do this.
As mentioned in the comments, you're missing the { }
brackets around your filter expression:
($Version.get_Keys() |Where-Object {$os.Caption -like "*${_}*" })
Another option is to use the intrinsic .Where({})
method:
($Version.get_Keys().Where({$os.Caption -like "*${_}*"}, 'First')
The First
mode flag will cause .Where({})
to return as soon as it found a match, preventing you from accidentally resolving multiple labels at once.
If you have a preferred order, make sure you use an ordered dictionary literal instead of a hashtable:
$Version = [ordered]@{
'Windows 10' = 'WIN10'
'Windows 11' = 'WIN11'
'Server 2022' = 'SVR2022'
'Server 2019' = 'SVR2019'
'Server 2016' = 'SVR2016'
'Server 2012' = 'SVR2012'
'Server 2008' = 'SVR2012'
}
Note: The use of .get_Keys()
rather than just .Keys
in the example above is deliberate - PowerShell's dictionary adapter prefers key-mapping over .NET members, so if you accidentally fill in an entry with the key Keys
you'll get unexpected behavior:
PS ~> $table = @{ A = 1; B = 2; C = 3; Keys = @('lol') }
PS ~> $table.Keys # oops
lol