Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Testing PowerShell HashTables

Posted on January 14, 2016

So I've been watching the PowerShell Toolmaking Fundamentals course on Pluralsight authored by Adam Bertram.  You may be surprised that I watch other PowerShell related courses, but I always pick up something I didn't know about, find a new teaching technique or something else that makes me say, "that was cool." I have found a few of these in Adam's course so far.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

One of the tricks he demonstrated was using a hashtable as a parameter value for an advanced function that could then be splatted to Set-ADuser.  For the sake of what I want to demonstrate here's my simplified version of such a function.

Function Update-MyUser {
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Position = 0, Mandatory, HelpMessage = "Enter a user name")]
[ValidateNotNullorEmpty()]
[Microsoft.ActiveDirectory.Management.ADUser]$Identity,
[Parameter(Position = 1, Mandatory, HelpMessage = "Enter a hashtable of parameter values for Set-ADUser")]
[ValidateNotNullorEmpty()]
[hashtable]$Settings
)

Write-Verbose "Updating $Identity"

Write-Verbose ($Settings | Out-String)
Try {
$user = Get-ADuser $Identity -ErrorAction stop
Write-Verbose $user.distinguishedname
}
Catch {
Throw $_
}

#splat the settings hashtable to Set-ADuUser

$user| Set-ADUser @settings

}

The function gets the specified user and then updates the user with hashtable of parameters from Set-ADUser.  If you know all the parameter names this works just fine.

image

I've easily updated the user account.

image

But what if I make a mistake with the hashtable of settings?

image

There is no parameter called FirstName for Set-ADUser. It should be GivenName. One thing you could do, and this is the point of this article,  is to  validate the hashtable keys against parameter names from Set-ADuser.

You can use Get-Command to list all of the parameter names.

get-command Set-ADuser | Select -expand Parameters

image

What we need to do is make sure that all of the keys in the settings hashtable are in this list. Here's a quick test.

$s = @{Title="T";Description="d"}
$p = get-command set-aduser | select -expand parameters

image

I can use code like this to test if the keys from $s are also in $p:

$s.keys | where {$p.keys -contains $_}

image

Although I may be more interested in the cases where they don't match.

$s.keys | where {$p.keys -notcontains $_}

This won't give any results because nothing matches the filter. But if I modify the hashtable with a bogus entry it will.

image

With this concept in mind I can revise the function.

Function Update-MyUser {
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Position = 0, Mandatory, HelpMessage = "Enter a user name")]
[ValidateNotNullorEmpty()]
[Microsoft.ActiveDirectory.Management.ADUser]$Identity,
[Parameter(Position = 1, Mandatory, HelpMessage = "Enter a hashtable of parameter values for Set-ADUser")]
[ValidateNotNullorEmpty()]
[hashtable]$Settings
)

#get parameters for Set-ADUser
$setparams = Get-Command -Name Set-ADuser | Select -ExpandProperty Parameters
#get keys from Settings that aren't in $SetParams.
$bad = $settings.Keys | where {$setparams.keys -notcontains $_ }

if (-Not $Bad) {

Write-Verbose "Updating $Identity"

Write-Verbose ($Settings | Out-String)
Try {
$user = Get-ADuser $Identity -ErrorAction stop
Write-Verbose $user.distinguishedname
}
Catch {
Throw $_
}

$user| Set-ADUser @settings

}
else {
Write-Warning "The Settings hashtable contains these bad keys: $($bad -join ",")"
}
}

image

Certainly you could add other code to list the available parameters, suggest corrections or whatever. But now the function won't attempt to run and gracefully handles bad keys.

Once corrected, the function works as expected.

image

And please don't take any of this as an indication that Adam missed something in his course. Far from it.  No course can teach you absolutely everything you need to know to build effective PowerShell tools. You need to build what works for you and add error handling that you feel is appropriate. In this case I thought this would offer a nice learning opportunity for you to learn about hashtable keys and a few operators.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

4 thoughts on “Testing PowerShell HashTables”

  1. Dave Brannan says:
    January 14, 2016 at 12:17 pm

    Sounds like a great test case for Pester!

    1. Jeffery Hicks says:
      January 14, 2016 at 12:53 pm

      On one hand yes, but in my scenario it is probably more about parameter validation. In fact, now that I write that I have another thought on the subject.

  2. Jeffery Hicks says:
    January 14, 2016 at 1:01 pm

    Another option, since the whole point here is parameter validation is to do just that. I moved the test code into a [ValidateScript()] test. If there is a failure then I throw a custom error message.

    Function Update-MyUser {
    [cmdletbinding(SupportsShouldProcess)]
    Param(
    [Parameter(Position = 0, Mandatory, HelpMessage = "Enter a user name")]
    [ValidateNotNullorEmpty()]
    [Microsoft.ActiveDirectory.Management.ADUser]$Identity,
    [Parameter(Position = 1, Mandatory, HelpMessage = "Enter a hashtable of parameter values for Set-ADUser")]
    [ValidateScript({
    $setparams = Get-Command -Name Set-ADuser | Select -ExpandProperty Parameters
    $bad = $_.Keys | where {$setparams.keys -notcontains $_ }
    if ($Bad) {
    Throw "The Settings hashtable contains these bad keys: $($bad -join ",")"
    #$False
    }
    else {
    $True
    }
    })]
    [hashtable]$Settings
    )

    Write-Verbose "Updating $Identity"

    Write-Verbose ($Settings | Out-String)
    Try {
    $user = Get-ADuser $Identity -ErrorAction stop
    Write-Verbose $user.distinguishedname
    }
    Catch {
    Throw $_
    }

    $user| Set-ADUser @settings

    }

  3. Glenn says:
    January 18, 2016 at 2:40 am

    Awesome! Thanks for sharing Jeff!

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d