Search code examples
powershellhashtable

powershell find which hash table key is contained in a string


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.


Solution

  • 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