on 13-Jan-2009 09:55
Welcome to this addition of the PowerShell ABC's where you'll find 26 posts detailing a component of the PowerShell scripting language, one letter at a time. Today's letter is the letter "P" and for it I'll cover the basics of defining input values, or Parameters.
Parameters (or arguments) are how you customize the actions of a command. There are 4 types of commands in PowerShell, scripts, functions, Cmdlet's, and External Commands.
Scripts and Functions are the areas I'm going to focus on here and I'll show you how parameters are defined in those two command types.
Scripts, for those that don't know, are essentially a text file with a series of PowerShell commands. PowerShell scripts typically end with the .ps1 extension and can be executed by the PowerShell interactive console by just typing in the script name. For anyone with any scripting background at all, you will know that you can't get much done without being able to make the script more dynamic by allowing input from the user to change the behavior or the script. Whether this is a subcommand to execute or login credentials to a service the script is trying to access, having the ability to pass them is fairly important to making the script a success.
$args
Script level parameters can be accessed in two ways. The first is with the $args variable which is a built-in variable that is auto-populated with an array of objects containing the values passed to the script.
---- Begin script foo.ps1 ----
Write-Host "Num Args:" $args.Length;
foreach ($arg in $args)
{
Write-Host "Arg: $arg";
}
---- End script foo.ps1 ----
PS C:\> .\foo.ps1
Num Args: 0
PS C:\> .\foo.ps1 foo bar
Num Args: 2
Arg: foo
Arg: bar
This is very similar to how other scripting languages work such as Perl. While the $args variable is a simple way to get at the arguments to a script, it requires a bit of work to do anything beyond simple examples.
The param statement
PowerShell provides a much more convenient way to declare formal parameters for a script with the param statement. The param statement must be the first executable line in the script with only comment or empty lines preceding it. The format of the param statement is
param([type]$p1 = , [type]$p2 = , ...)
Where the type literal "[type]" and initialization values "= " are optional components to allow for type specification and specifying initial values respectively.
There are three types of parameters in PowerShell
Parameter Type | | | Formal name in Powershell | | | Example |
---|---|---|---|---|
Switches | Switch Parameters | Get-ChildItem -Recurse | ||
Options | Parameters | Get-ChildItem -Filter *.cs | ||
Arguments | Positional Parameters | Get-ChildItem *.cs | ||
Arguments are positional parameters becuase they are always associated with a parameter name but it's permitted to leave the name out and let the interpreter figure out what parameter is it from it's position on the command line.
Switch parameters are just the opposite in that you specify the parameter but the argument is left out. The interpreter assigns the parameter a value based on whether the parameter is present or not. To specify a switch type parameter, you should use the "[switch]" type literal in the parameter declaration.
The following script is functionally equivalent to the one above, but now the parameters are declared and strongly typed.
---- Begin script foo.ps1 ----
param([string]$foo = "foo", [string]$bar = "bar")
Write-Host "Arg: $foo"
Write-Host "Arg: $bar"
---- End script foo.ps1 ----
PS C:\> .\foo.ps1 -foo "foo" -bar "bar"
Arg: foo
Arg: bar
In this example the arguments can be treated as Options or Arguments by including or omitting the "-name" qualifiers in the command execution.
Functions are defined by the function statement:
function () {}
The format of the parameter list is identical to that of the param statement. The above script can be converted to a function as follows
function foo([string]$foo = "foo", [string]$bar = "bar")
{
Write-Host "Arg: $foo";
Write-Host "Arg: $bar";
}
The param statement is supported in functions as well so if you do not wish to specify it in the function declaration, you can do so in the first line of the function as follows:
function foo()
{
param([string]$foo = "foo", [string]$bar = "bar");
Write-Host "Arg: $foo";
Write-Host "Arg: $bar";
}
In PowerShell, the key to metaprogramming (or writing programs that write or manipulate other programs), is something called the scriptblock. This is a block of script code that exists as an object reference but does not require a name. The Where-Object and Foreach-Object Cmdlets rely on scriptblocks for their implementation. Scriptblocks are also known as anonymous functions or lambda expressions in other languages. A scriptblock is defined with the following syntax
{ param() }
This looks similar to a function definition above without the function keyword, name, and parameter list in the declaration. In the case of scriptblocks, parameters are defined with the param statement as the first command in the scriptblock.
Keeping with the above example, I'll show that functionality defined within a script block.
PS C:\>& {param([string]$foo = "foo", [string]$bar = "bar") Write-Host "Arg: $foo"; Write-Host "Arg: $bar"; }
Arg: foo
Arg: bar
If you were wondering about the "&" in there, that's how you tell PowerShell to invoke that literal as a block of code.
Good luck!
-Joe
A "switch" type doesn't take a value, it's "true" if you pass the "-Param2" param is passed in without values.
By using the "boolean" type I get the following results.
--------------------------
param([int]$Param1 = 0, [boolean]$Param2);
Write-Host $Param1, $Param2;
--------------------------
PS > .\test-bool.ps1 123 $false
123 False
PS > .\test-bool.ps1 123 0
123 False
PS > .\test-bool.ps1 123 $true
123 True
PS > .\test-bool.ps1 123 1
123 True
PS > .\test-bool.ps1 123 123456
123 True
Hope this helps...
-Joe
blogs.technet.com/.../...mandatory-parameters.aspx
Or you could use a default value with a throw statement
param($val = $(Throw "parameter val required!"));
Cheers!