Tuesday, December 24, 2019

Changing Default Parameter Values - Yet Another User for Hash Tabales

In PowerShell, the hash table is an amazingly useful .NET class - for all sorts of things: With hash tables, you can:

  • Pass a hash table and an object to Select-Object, and have the cmdlet add a calculated property to the object for later use
  • Push a hash table to Format-* and have the command create and display a new property and have it look just the way you want it.
  • Splatting, splatting, and more spatting. What a great use of hash tables.
  • Specifying property values for obscure properties in Set-ADUser/Set-ADComputer, and Set-AD-Object.
  • And many more!
But one of my favourite uses is to change the default values for certain properties within a PowerShell session or even a script.

Herre's something I am sure you have all faced. If you run a PowerShell job, you receive the output generated by using Receive-Job. By default, once you run that command, the output is removed from memory and is no longer available. Of course, you could use the -Keep parameter - if you remembered to, which I often don't.  My muscle memory is kind of not yet that well developed in this regard. So I often find my self losing output (which takes time to reproduce). I'd like to do better!

There are other commands too, that I just prefer a different value for some parameters. I'm not saying that the developers were wrong with the defaults they chose, it's just that I prefer different values. For each of these, for example -Wrap with Format-Table, I'd like to tell PowerShell to use a different default setting for a parameter on one more command. 

As ever with PowerShell - you can have it your way, and of course, there's a script for that!

The basic hashtable class is System.Collections.Hashtable. Developers across the Windows and increasingly the Linux also create specific objects derived from the hashtable class. You can read about the hash table class at: https://docs.microsoft.com/en-us/dotnet/api/system.collections.hashtable?view=netcore-3.1. The class is broadly the same in the full .NET and .NET core.

So how does this help to set default command values? When Windows PowerShell and PowerShell startup, the engine creates a variable: $PSDefaultParameterValues.  This variable is of type
System.Management.Automation.DefaultParameterDictionary which you can read about at: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.defaultparameterdictionary?view=pscore-6.2.0. This object is a hash table with some improvements when used for parameter caching.

You add rows to this hash table to describe the command name, parameter name, and the new value you want PowerShell to use subsequently. For the key name, you specify the command and parameter as "<Command name>: then specify the value you want for that parameter. And of course, you can use wild cards to specify the command or property names.  You build this hash table either in a script (meaning that all commands in that script have a different default value) or stick it in the profile as I so.  So, for example, if you wanted to ensure that Receive-Job always used the -KEEP parameter, you would specify:
$PSDefaultParameterValues  @{Receive-Job:Keep = $true}
My standard profile on my laptop sets this and other values:
$PSDefaultParameterValues = @{'*:AutoSize'=$true;  '*:Wrap'=$true;'Receive-Job:Keep'=$true}
This way, any command that has an AutoSize parameter (eg Format-Table, always uses -AutoSize, likewise for any command that uses the  -Wrap parameter).

I just love hash tables - and this is another great example of where you can use one to have it your way.  


1 comment:

Schwitzd said...

Ciao Thomas,
command should be like that:
$PSDefaultParameterValues = @{"*:AutoSize" = $true; '*:Wrap' = $true; 'Receive-Job:Keep' = $true}