How To Use PowerShell's $PsBoundParameters Variable
Here's how to use this automatic variable to write cleaner code.
- By Adam Bertram
One of the features I like about PowerShell is automatic variables. Automatic variables save you time and provide a more consistent approach at figuring out what's going on under the hood of your PowerShell session. Automatic variables are always available and always contain the data you expect. You won't find an automatic variable assigned some obscure variable you forgot you set 100 lines earlier in your script which is why I always rely on them when I can.
What is the $PsBoundParameters Variable?
One automatic variable I use all the time is $PsBoundParameters. $PsBoundParameters is a hashtable-like variable, more specifically a [System.Management.Automation.PSBoundParametersDictionary] object. This variable is present if a script or function you create that contains user-populated parameters. In other words, if you've got a script or function using the param() statement with one or more parameters inside and you've passed arguments to these parameters, the $PsBoundParameters variable will always be available.
Here's an example: I have a single parameter for my C:\Test.ps1 script called param1. I've also set a default value of "default value" for param1. The only line in my functional line in my script is outputting the value of $PsBoundParameters. You see that when I just execute the script I get no output. This is because $PsBoundParameters is null without any parameters populated even if I set a default value.
However, when I explicitly pass in the "my value" value into the param1 parameter I immediately get back a key/value pair inside of a dictionary object with the key name being the parameter name and the key value being the parameter value.
How to Use $PsBoundParameters to Your Advantage
The $PsBoundParameters variable is an extremely handy automatic variable to use when a script or function contains one or more parameters being called. It allows you to not only make scripts or functions more efficient by saving lines of code but it also prevents you from fat-fingering. Here's a couple great examples of ways to to utilize it.
Using $PsBoundParameters for Validation: Let's say I've got a script I created that has an important parameter that must exist called ImportantParam. I set this parameter to Mandatory in the param itself but due to some specific circumstances I chose not to use parameter validation to ensure it meets the criteria I expect. Inside the script I need to verify that the parameter was explicitly passed.
I can use the ContainsKey() method on the $PsBoundParameters variable to first check to ensure the parameter was used prior to doing something with that value. By making this practice part of your routine script writing habits you'll encounter far less errors because you have more control over your script.
Along those same lines, you can also use $PsBoundParameters to check for the existence of a parameter with a specific value, how many parameters were explicitly called and a lot of other things. Here are all of the methods and properties you have at your disposal.
Using $PsBoundParameters for Code Efficiency: This is a trick I use sometimes to get around manually typing in all of the parameter names if I have a need to do some common action to them all at runtime; I use a foreach loop.
I've got a script that has 5 parameters. Each of these parameters is a file path pointing to a text file. I need my script to read the contents of each of these files as one of the first steps and assign each to a variable. I could do something like this:
However, this is extremely ugly and inefficient. As soon as I see repeating code like that I automatically think to implement a loop of some sort. Now, let's use $PsBoundParameters to make this much prettier.
In this example, I'm using the GetEnumerator() method available on all dictionary objects and hashtables in order to break that object apart so I can loop through each key/value pair inside. I'm then using a counter $i to keep track of each incrementing number. I'm then creating a variable called $File1, $File2, etc and assigning the contents of whatever text file is specified in the $FilePath1, $FilePath2, etc parameters.
Finally, to just demonstrate that this actually worked, I'm using Get-Variable to display the contents of the each text file.
By using a foreach loop here I'm able to account for more than five FilePath params, if necessary. I also don't have to risk fat-fingering some code. Using this method is a much better approach leveraging the data inside of $PsBoundParameters.
Using $PsBoundParameters is a great way to make your code cleaner and more efficient. By leveraging the parameter names and values in this manner prevents reinventing the wheel by creating variables with duplicate values as those inside the dictionary object already. It gives you an easy way to see which parameters were explicitly called vs. which ones were simply default values and allows you to create some simple or very complex validation routines to ensure you're the parameter values are as you expect.
Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.