Mandatory parameters in PowerShell
One of the most frequently question I get when teaching parameters in PowerShell is regarding mandatory parameters.
To answer that, let us back up a little bit and talk about parameters in general.
We know that in a script (or function) we can use $args to capture any argument that is passed and is not bound to any parameter:
which presents the following output:
Additionally, even if we have a formal parameter definition, any unbound parameters will be found in $args:
Note, however, that if we do not pass any arguments, the $StringParameter value is an empty string.
This stems from the fact that the PARAM section declares $StringParameter’s type as [string] , so it gets initialized to an empty string.
We could assume a default value for the parameter for those cases in which the user does not provide an argument:
However, in many cases, we cannot assume any value for parameters. Take the case where we create a script to read a file that contains a bunch of server names on which to do some processing:
In this case, chances of finding a file “Servers.txt” in a folder “PSDemo” on the root of the drive C: are very limited to the machine of the owner of the script.
One easy way to force users to enter the parameter is by assigning an expression that throws an exception as the default value for the parameter. In this way, if an argument cannot be bound to the $FileName parameter, the expression is evaluated, and an error is presented:
Now, here is where mandatory parameters come into place. What if instead of a nasty error like the one above, we implement something more elegant? After all, when PowerShell is not given enough information, sometimes, it will politely ask for it like in the following example:
We told PowerShell that we want to remove an item, but we did not provide information on what item to remove. PowerShell did not raise an exception, nor did it assume any particular item (imagine what would happen if it did!). Instead, it presents us with a prompt to provide the argument for the parameter $Path.
We can implement the same functionality by adding some metadata to the parameter, thus fine-tuning the parameter definition. This metadata is provided via Attributes. In this case, an attribute can be used to qualify the parameter $FileName. Parameter attributes have parameters themselves. We’ll provide values to this parameters to indicate that we want the parameter to be mandatory. Note the syntax in the PARAM section:
In this case, the attribute called Parameter can take a parameter called Mandatory. We are passing the value $true as its argument (a bit confusing, huh?). Note that the parameter definition is taking up two lines of code. This is done by convention, for readability. However, that is the same as:
Now that we have indicated that the parameter is mandatory, notice that PowerShell is able to understand that it cannot do anything without that value, so it simply asks the user for it:
Parameter attributes are not the only type of attributes used to provide metadata to a script or function. There are far more advanced scenarios that can be implemented via attributes, but they are subject matter for future posts.
I hope this brings a bit nicer user experience to your scripts as well as extended functionality with very few changes.