PowerShell has some nice built-in command line parameter parsing. I’ve only been wishing for something like this for … well, forever.
Imagine you have a script that accepts four parameters:
-EnvironmentName (or -e), which is mandatory
-DestinationDir (or -d), which is mandatory
-UserName (or -u), which is optional
-Password (or -p), which is optional
Usage would be:
myscript -e testing -d c:\test -u username -p password
Writing code to parse and verify those parameters is just busy work. But because we haven’t had a good alternative (at least, not on the Windows platform), we’ve been doing it for years, writing new argument parsing code for every program. Sure, there’ve been some attempts at building a generalized argument parser and validator for particular languages or platforms (like .NET), but not one of those has really caught on.
Until now. PowerShell makes quick work of parameter parsing and validation. You can describe the arguments for the script mentioned above with just a few lines of code.
# ParamTest.ps1 - Show some parameter features
# Param statement must be first non-comment, non-blank line in the script
Param(
[parameter(Mandatory=$true)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true)]
[alias("d")]
$Destination,
[alias("u")]
$UserName,
[alias("p")]
$Password)
Write-Host "EnvironmentName = $EnvironmentName"
Write-Host "Destination = $Destination"
Write-Host "UserName = $UserName"
Write-Host "Password = $Password"
At a PowerShell prompt, run that script by entering this command:
.\ParamTest -EnvironmentName MyEnvironment -Destination c:\logs\MyEnvironment
The script will output the parameters as you entered them. The UserName
and Password
arguments are optional, so the output for them will be blank. If you want, you can include default values for those optional arguments.
I like that you can specify aliases for the parameters. So -e MyEnvironment
is the same as -EnvironmentName MyEnvironment
.
Note also that -d dest -e env
will do the rational thing. That is, the order that you specify arguments doesn’t matter. Well, it does matter if you don’t name the parameters on the command line. That is, .\ParamTest MyEnvironment c:\logs\MyEnvironment
will assign the value “MyEnvironment” to $EnvironmentName
, and “c:\logs\MyEnvironment” to $Destination
.
Unfortunately, there seems to be a bug in the positional parameters stuff. According to the documentation, if you have a parameter
attribute on a parameter, then the default is that the parameter can’t be positional. If you use a parameter
attribute, you’re supposed to include a Position
argument if you want it to support positional processing. That is, in the above code, you should have:
Param(
[parameter(Mandatory=$true, Position=1)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true, Position=2)]
Conversely, if you don’t want any positional parameters, you should be able to write:
Param(
[parameter(Mandatory=$true)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true)]
[alias("d")]
$Destination,
[parameter()]
[alias("u")]
$UserName,
[parameter()]
[alias("p")]
$Password)
That doesn’t seem to work. The code above will still support positional parameters. I haven’t yet seen a good way to completely eliminate positional processing.
You can try parameter(Position=-1)
, but then you’ll get an exception if you try to run get-help
on your script. I’ve also seen a hack of using Position=0
on all of the parameters, but that results in some unhelpful error messages if you forget to name your command line parameters.
Even with the oddities having to do with positional parameters, the Param
statement is a welcome feature in any programming language.
What I’ve shown above barely scratches the surface of what you can do with Param
. You can include a help message with each parameter, create parameter sets, and specify some basic argument validation, all with some simple syntax in the Param
statement. If you’re writing scripts or cmdlets, you should study the Param
statement.
If, like me, you’re relatively new to PowerShell, it can be difficult to find information about this stuff. A good place to start is the MSDN Windows PowerShell topic. I’ve been unable to find a PowerShell reference on MSDN. For reference material, I start at the TechNet PowerShell page. For information about Param, see about_Functions and about_Functions_Advanced, or type help about_Functions
(or help about_Functions_Advanced
) at a PowerShell command line.
The documentation I’ve seen lacks good examples, but a little searching and experimenting can yield good results.
With PowerShell, there’s simply no reason to write another batch file. And if you find yourself making large modifications to an existing batch file, you should think very seriously about just rewriting it to use PowerShell. It really is worth your time to learn and use it. I think you’ll find, as I have, that many of those little C# programs you’ve been writing to do various things can be replaced with simple PowerShell scripts.