5 min read
Tip #3: Utilizing external config data in PowerShell (1/4)
Tobias & Aleksandar's tip #3:
The two very well-known PowerShell experts have teamed up to share their best and most...
PSDefaultParameterValuesis a hashtable allowing us to overwrite default values of any parameter on any cmdlet with our own desired default values.
The cmdlet will then use the custom default value unless a different value is specified in the command.
This may not sound like the most important feature but trust me, after this post you will ask yourself how you ever worked without it.
$PSDefaulParameterValues.Add("Command:Parameter","Value")
As you can see we simply add a new key to the hashtable specifying the cmdlet and parameter to set a default for, separated by a :. The value obviously needs to be of a type accepted by the parameter or you will get errors when using the cmdlet.
A concrete example would be to specify a custom separator for Write-Host.
# Default PS> Write-Host "Hello","World" Hello World # Adding the custom default PS> $PSDefaultParameterValues.Add("Write-Host:Separator", "`n") # Changed output PS> Write-Host "Hello","World" Hello World
For example, we could use it to enable debugging for all Invoke-WebRequest calls in a script at once.
# Default, no verbosity PS> (Invoke-WebRequest "https://ps1.guru").StatusCode 200 # Adding the custom default PS> $PSDefaultParameterValues.Add("Invoke-WebRequest:Verbose", $true) # Changed output, with verbosity PS> (Invoke-WebRequest "https://ps1.guru").StatusCode VERBOSE: GET https://ps1.guru/ with 0-byte payload VERBOSE: received 4801-byte response of content type text/html 200
PS> $PSDefaultParameterValues.Add("*:Verbose", $true)
Staying with our verbosity example from before we could make its behavior dependent on a variable $verbose.
PS> $PSDefaultParameterValues.Add("*:Verbose", {$verbose -eq $true})
Now we can control the default verbosity of our session by setting and removing a variable. Keep in mind this script block is run every time you use the cmdlet, so keep it fast. You can measure it like this:
PS> Measure-Command {$verbose -eq $true} | ft Days Hours Minutes Seconds Milliseconds ---- ----- ------- ------- ------------ 0 0 0 0 0
Get-History | Where-Object CommandLine -like "`$PSDEfaultParameterValues*"
Let’s say you always export data to CSV files for someone to open in Excel. If they just double-click your CSV they will not get a great result.
Most of us would then simply open up a new Excel file and import the data with Data > From Text, clicking through the plethora of screens and configuring Excel to actually detect the delimiter.
But there is a better way! Instead of just exporting CSV.
Get-Process -Name Microsoft* | Export-Csv msproc.csv
you could specify a custom delimiter and, while your at it, remove type information and clobber.
Get-Process -Name Microsoft* | Export-Csv bettermsproc.csv -Delimiter ";" -NoTypeInformation -NoClobber
Now importing, exporting, converting from and converting to CSV will use the delimiter ; and not include any type information or clobber.
If you open the resulting CSV file directly with excel you can see a result similar to the data import dance we did before.
But always typing out those parameters is cumbersome and has an inherently high margin of error.
This is where we will set some defaults
$PSDefaultParams.Add("Export-Csv:Delimiter", ";") $PSDefaultParams.Add("Export-Csv:NoTypeInformation", $true) $PSDefaultParams.Add("Export-Csv:NoClobber", $true)
With this we can go back to simply using Export-Csv and the resulting file will be opened in Excel just as expected.
We could even go one step further and change those parameters for all cmdlets in the CSV family using wildcards.
$PSDefaultParams.Add("*-Csv:Delimiter", ";") $PSDefaultParams.Add("*-Csv:NoTypeInformation", $true) $PSDefaultParams.Add("*-Csv:NoClobber", $true)
in your scripts.
There are some good reasons for this:
To mitigate this I would suggest just disabling PSDefaultParameterValues first thing in all your scripts:
# Disable PSDefaultParameterValues $PSDefaultParameterValues.Add("Disabled", $true)
And re-enabling them at the end:
# Re-Enable PSDefaultParameterValues $PSDefaultParameterValues.Remove("Disabled")
Sep 4, 2024 by Dr. Tobias Weltner and Aleksandar Nikolić
The two very well-known PowerShell experts have teamed up to share their best and most...
Sep 4, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
The two very well-known PowerShell experts have teamed up to share their best and most...
Sep 4, 2024 by Dr. Tobias Weltner and Aleksandar Nikolić
The two very well-known PowerShell experts have teamed up to share their best and most...
Marco is a DevOps engineer at heart and uses PowerShell in combination with other stacks to automate deployment, perform data analytics, and bring enterprises to the cloud. He has been using PowerShell as his primary command line on all platforms since 2018 and is always trying to get more people to switch from bash and others.