PowerShell 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

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

SwitchesSwitch ParametersGet-ChildItem -Recurse
OptionsParametersGet-ChildItem -Filter *.cs
ArgumentsPositional ParametersGet-ChildItem *.cs

Internet_argumentArguments 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

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";
}

Scriptblocks

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.