Welcome to the next post in my Next-Level Scripting series where I show you the PowerShell scripting techniques that take your scripts to the next level – a level defined by concise, well-written code that conforms to best practices and uses the built-in tools in PowerShell whenever possible to handle common scripting tasks.
In this post we’ll be taking a look at a slightly more advanced feature of parameters in PowerShell which allows you to create mutually exclusive parameters. If you are not familiar with parameters yet, I suggest you take a look at Part I and Part II in this series first before proceeding.
What are mutually exclusive parameters?
If you’ve done some basic scripting with PowerShell you’ve probably come across mutually exclusive parameters. Take, for example, Get-Process. It has two parameters, –Name and –Id, to retrieve processes by name or process id respectively. If you stop and think about it for a second, you only want to allow the Name or Id parameter to be used each time the cmdlet is run. If you allowed both at the same time then you would in essence be allowing someone to retrieve a process by Name and Id, something which is bound to lead to problems. And this is the concept of mutually exclusive parameters – when you select one parameter, one or more other parameters become unavailable for use. Let’s take a look at how we do this.
Complicated Copy
Let’s imagine you’re writing a script to copy some files on an ad-hoc basis to random servers. Some of the servers you will target are inside your network and accessible via name while others are behind a firewall and only accessible via IP address. Furthermore, you have multiple firewalls and depending on which zone the target computer is in, you want to copy a different set of files. These are the required parameters for our script:
- Computer name
- IP Address
- Firewall zone name
There’s more to it though – we only want to allow the following parameter combinations:
- Computer name only
- IP Address and firewall zone name only
What we don’t want is to allow the computer name and IP address to be specified at the same time. So the challenge is: how do we set up our parameters so that once the computer name parameter has been selected, IP address and firewall zone name are no longer available and vice versa?
Game, ParameterSet and Match
The key to achieving this is using Parameter sets. This feature allows you to categorize your parameters into different groups such that once a parameter from one group is selected, any parameter which belongs to a different group is no longer available. This is the code to set up the parameters according to our requirements for our fictitious file copy script:
| 001 002 003 004 005 006 007 008 009 010 011 | param ( [Parameter(ParameterSetName = "NameCopy")] $computerName, [Parameter(ParameterSetName = "IPCopy")] $IPAddress, [Parameter(ParameterSetName = "IPCopy")] $FwZone ) |
As you have probably guessed by now, the ParameterSetName is the key here. We have created two groups of parameters:
Group 1 Name: NameCopy
Group 1 Parameter: $computerName
Group 2 Name: IPCopy
Group 2 Parameters: $IPAddress, $FwZone
We have now prevented anyone running our script from selecting both the computer name and IP address parameter at the same time. In addition, the firewall zone parameter will only be available with the IP address parameter. Let’s take a look at the output if we run help Copy-MyFiles.ps1, the name of our hypothetical script.
Isn’t that a beautiful sight? Notice how the two possible combinations shown in the help output adhere to how we structured out parameter sets. PowerShell has taken care of documenting our parameters for us and all someone has to do to find out what parameter combinations are acceptable is to run help on our script.
NOTE: To keep things simple, I did not make these parameters mandatory as shown in the previous posts in this series on parameters. As a best practice, you should include the Mandatory attribute for these parameters since none of them are optional. This is how our param block would look with this addition:
| 001 002 003 004 005 006 007 008 009 010 011 | param ( [Parameter(Mandatory = $true, ParameterSetName = "NameCopy")] $computerName, [Parameter(Mandatory = $true, ParameterSetName = "IPCopy")] $IPAddress, [Parameter(Mandatory = $true, ParameterSetName = "IPCopy")] $FwZone ) |
Conclusion
We’ve taken our file copy script parameters to the next level in this post by using Parameter sets to group our parameters. This approach prevents the person running our script from accidentally executing it with a parameter combination which will cause our script to behave unpredictably – something you definitely want to avoid at all costs.
No comments:
Post a Comment