An Array of Hash Tables


Welcome to the 293rd post on tommymaynard.com. It’s countdown to 300!


If you’ve ever looked into Pester and TestCases, then maybe you’ve seen what I’m about to mention. While today’s post has nothing to do with Pester, this feature in Pester uses an array of hash tables. Neat, right? While adding a couple New-PSDrive commands to my PowerShell profile, I moved from this first option,…

$Param = @{
    Name = 'IDT'
    Root = '\\tommymaynard.com\Windows\Internal\Users\tommymaynard'
}
New-PSDrive @Param -PSProvider FileSystem | Out-Null

$Param = @{
    Name = 'IDI'
    Root = '\\tommymaynard.com\Windows\Internal'
}
New-PSDrive @Param -PSProvider FileSystem | Out-Null

…to something else.

While the use of splatting is a bit more grown-up than creating long, multi-line wrapping commands, there’s no reason why we should be executing the same command — New-PSDrive, in this instance — outside of a looping construct. That was my thought today, anyway. If we need to invoke the same cmdlet or function more than once, it should only be entered into our code, once. It is possible there’s an exception here, but for the most, I stick to this belief.

But how do I combine multiple hash tables in to looping construct? Well, my solution had everything to do with my quick remembrance of Pester and TestCases. For fun, we’ll link to a quick example from a Pester issue I recently created in GitHub. This offers us a good example. See the third It block in the Pester example in number 4 (“Current Behavior”). Do you see that? It’s an array of hash tables. Perfect example for what I needed.

As we create our hash tables, we need to ensure they’re being added to an array. Then we can loop through our array elements with ForEach, or ForEach-Object. I’ll include examples for both. First, however, let’s create our array of hash tables.

$HashTableArray = @(
    @{
        Name = 'IDT'
        Root = '\\tommymaynard.com\Windows\Internal\Users\tommymaynard'
    },
    @{
        Name = 'IDI'
        Root = '\\tommymaynard.com\Windows\Internal'
    }
)

And now, let’s ensure what we have, is where we want it, and want we want.

PS > $HashTableArray

Name                           Value
----                           -----
Root                           \\tommymaynard.com\Windows\Internal\Users\tommymaynard
Name                           IDT
Root                           \\tommymaynard.com\Windows\Internal
Name                           IDI

As mentioned, there’s a couple way to loop though these. One is using a Foreach construct — which is the first below example — and one is using the ForEach-Object cmdlet. They’re both below, and listed in the respective order in which they were discussed. So yes, if you’re calling the same command outside of looping construct, you need to consider how to do better, if you can. There’s no reason in my instance that New-PSDrive should be in a our code more than once.

Foreach ($HashTable in $HashTableArray) {
    New-PSDrive @HashTable -PSProvider FileSystem | Out-Null
}

$HashTableArray | ForEach-Object {
    New-PSDrive -Name $_.Name -PSProvider FileSystem -Root $_.Root | Out-Null
}

If you didn’t notice, I’ve piped my New-PSDrive commands to Out-Null. This was done in order to remove the output that would’ve otherwise been produced.

One thought on “An Array of Hash Tables

  1. John Strode

    Tommy,

    I’d like to know how I can add key, value entries to each of the arrays in the following collection.

    $SRV2016 = @()
    $SRV2016 = (Get-ADComputer -Filter { OperatingSystem -Like ‘*Windows*Server*2016*’ } -Properties OperatingSystem).name
    $SRV2016 = @($SRV2016 | Test-NetConnection -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Where-Object {$_.pingsucceeded -eq $true} | Select-Object -ExpandProperty computername)
    $HashTableArray = [ordered]@{} | Set-Variable $SRV2016

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *