How to set mandatory parameters using parameters sets in PowerShell
Tags: powershell, showdev, productivity
Published: 2020-03-21 13:09:39

In this article, I want to show you how to force your users to pass the proper arguments to your _PowerShell scripts_ depending on data. I found this way for creating more readable code using fewer lines of code and get the proper parameters from the users showing them the ones the have to type.

You probably know about __required parameters__ in _PowerShell_ and how to declare them but if you don't, please, take a look at this [article](https://devblogs.microsoft.com/scripting/use-powershell-to-make-mandatory-parameters/). The __Mandatory__ parameter attribute appeared on _PowerShell 2.0_ and made easier to declare required parameters instead of evaluating it in code and throwing the proper error messages to the user when running it.

```PowerShell
 param(
    [Parameter(Mandatory)]
    [String] $Message
)

Write-Host $Message
```

But, what happens when my script could have mandatory parameters depending on the value of other parameters? Let's say I have a script to prepare my morning tea every day. I like tea with milk and sugar or just alone with honey. So, how to code this?

```PowerShell
param(
    [Switch] $Honey,
    [Switch] $Milk,
    [int] $Sugar
)

If($Honey -eq $true) {
    Write-Host "Your tea with honey is ready"
} ElseIf($Milk -eq $true -and $Sugar -gt 0) {
    Write-Host "Your tea with milk and sugar is ready"
} Else {
    Throw "Wrong information"
}
```

Is this a good approach? It depends on your requirements. In my opinion, this is something I would not comfortable with, I cannot see which parameters are mandatory or the paths the code has so, imagine all these issues in a production environment where different tasks must have been implemented.

One of the solutions you might do is to separate the code into two different scripts, one for tea with milk and the other for tea with honey. This will grow your PowerShell scripts library and it will seem that you have functionality repeated.

To solve these problems, the __ParameterSetName__ attribute helps us to have different groups of parameters and define their behavior for each case. Take a look at this [article](https://devblogs.microsoft.com/powershell/powershell-v2-parametersets/) for a complete explanation. It appeared in _PowerShell 2.0_ for the first time to help coders to create groups of parameters for their scripts. As an example, let's think when requesting API's methods, we could have _GET_ requests with empty _bodies_ and _POST_ requests with _body_ information as a must. The script is the same and covers the same functionality in both cases but parameters could be different depending on what we need to do.

Coming back again to my tea preparation script, we will use the __ParemeterSetName__ attribute to set two groups of parameters with _Honey_, in the first case, as mandatory, and _Milk_ and _Sugar_ mandatory for the second case. Let's see how the code is more readable and simple in the following example:

```PowerShell
param(
    [Parameter(ParameterSetName="Honey", Mandatory)]
    [Switch] $Honey,

    [Parameter(ParameterSetName="Milk", Mandatory)]
    [Switch] $Milk,
    [Parameter(ParameterSetName="Milk", Mandatory)]
    [int] $Sugar
)

Switch ($PsCmdlet.ParameterSetName) {
    "Honey" {
        Write-Host "Your tea with honey is ready"
    }

    "Milk" {
        Write-Host "Your tea with milk and sugar is ready"
    }
}
```

This approach is safer for your code because parameter checking relies on the _PowerShell engine_ and you don't have to worry about it. Another advantage appears when you get the information of your script using the `Get-Help` command. It will show you the two ways the script could be called giving the clues about the parameters you can use:

```PowerShell
PS > Get-Help Prepare-MyMorningTea.ps1

Prepare-MyMorningTea.ps1 -Honey [<CommonParameters>]
Prepare-MyMorningTea.ps1 -Milk -Sugar <int> [<CommonParameters>]
```

But it makes you focus on what you need to focus on: parameter definition and the code for each parameter group. This is the most important thing to me, you don't need to worry about checking for chain parameters and spend some time coding something aside to the real objective of the script.

I hope you enjoyed reading this article and wondering about the use of _ParameterSetName_ attribute for your next _PowerShell_ script. Leave any comment if you have any questions or want to share anything.