Saturday, January 03, 2009

Parameter Attributes in PowerShell V2 CTP Advanced Functions

In PowerShell V2 CTP3, you can create Advanced Functions which are, in effect, cmdlets written in script. I’ve already blogged about some of the cool features, particularly AutoHelp, which I find utterly cool! One neat aspect is the ability to define the parameters that your script accepts. Thus you can get PowerShell to do at least some of the validation of the parameter for you automagically. With Advanced Functions, you can do two things: you can define the parameter details in your script and have Get-Help provide them as documentation and you can decorate your script with Attributes telling PowerShell how to treat each parameter.

For many PowerShell users, the terms “decorate” and “attribute” may be new. By decorate, I mean just adding in extra text. Attributes are text that tell PowerShell how to do something. In CTP3, you can specify the [Parameter] attribute – decorating your script with these attributes (i.e. adding in the text to your script) enables you to tell PowerShell just how it should handle parameters to your script. I believe this is an important feature – and takes PowerShell further down the road towards being a full .NET language.

Here’s a snipped of code, a param block, showing the use of [Parameter] attributes:

  1. param
  2. [Parameter(Position=0, Mandatory=$false)] 
  3. [string] $Domain = "Cookham" ,     
  4. [Parameter(Position=1, Mandatory=$false)] 
  5. [string] $Computer = "Cookham8"
  6. [Parameter(Position=2, Mandatory=$false
  7. [string] $User     = "tfl"             

This parameter (param) block defines three script parameters ($domain, $computer, $user). The Parameter attributes are also specified using named attributes (eg Mandatory, Position, etc) to ensure PowerShell knows how to handle them. The documentation thus far on these parameter attributes is limited. Well, limited in terms of PowerShell documentation. The MSDN Library has a ton of documentation on how to write PowerShell Cmdlet, but these are written for C# programmers. I’m assuming that, in due course, there will be additional documentation that is more PowerShell focused.

If this script fragment were from a script called Get-Foo (ok bad name but work with me!), then you might call this script as follows:

PS C:\foo> Get-Foo NWTraders MyWorkstation BillyBob

In terms of Parameter attributes, http://msdn.microsoft.com/en-us/library/ms714348(VS.85).aspx contains a list of the name attributes you can use. These are:

  • Mandatory  - a boolean saying whether the parameter is required or not. A mandatory parameter that is not specified generates a run time exception.
  • ParameterSetName – a string naming the parameter set a parameter belongs to. You can use this name in your script to handle different sets of parameters (that result in different behaviour of your script).
  • Position – an integer specifying where parameter’s order. As you can see in the above example, the $User paramater is the third parameter, while $domain is the first and $computer the second.
  • ValueFromPipeline – a boolean indicating if the parameter can come from the pipeline.
  • ValueFromPipelineByPropertyName  - a boolean indicating whether the parameter is filled from a property of the piped-in object that has either the same name or the same alias as this parameter.
  • ValueFromRemainingArguments – a Boolean indicating whether this cmdlet accepts all the remaining arguments passed. This is a good way to pickup any overspecified parameters.
  • HelpMessage – a string containing a short description of this parameter.
  • HelpMessageBaseName – the base name of the help message resource.
  • HelpMessageResourceId – an identifier used when a help message is localised.

Here is a slightly longer script demonstrating some of these:

  1. <#
  2. .SYNOPSIS 
  3.     Shows Parameter attributes 
  4. .DESCRIPTION 
  5.     Script is decorated with Parameter attributes to demostrate the use of them 
  6. .NOTES 
  7.     File Name  : Get-ParameterAttribute1.ps1 
  8.     Author     : Thomas Lee - tfl@psp.co.uk 
  9.     Requires   : PowerShell V2 CTP3 
  10. .LINK 
  11.     To be posted at: 
  12.     http://www.pshscripts.blogspot.com 
  13. .EXAMPLE 
  14.     Simple usage, with partial parameters specified 
  15.     PS C:\foo> .\Get-ParameterAttribute1.ps1 abc 
  16.     ---- 
  17.     Domain    : abc 
  18.     Computer  : Cookham8 
  19.     User      : tfl 
  20.     ---- 
  21. .EXAMPLE 
  22.     Simple usage, with all parameters specified 
  23.     PS C:\foo> .\Get-ParameterAttribute1.ps1 kapoho, kapoho1, BigKahuna 
  24.     ---- 
  25.     Domain    : kapoho 
  26.     Computer  : kapoho1 
  27.     User      : BigKahuna 
  28.     ---- 
  29. .EXAMPLE 
  30.     Showing getting first parameter from the pipeline 
  31.     PS C:\foo> "abc", "def", "GHI" |.\Get-ParameterAttribute1.ps1 
  32.     ---- 
  33.     Domain    : abc 
  34.     Computer  : Cookham8 
  35.     User      : tfl 
  36.     ---- 
  37.     ---- 
  38.     Domain    : def 
  39.     Computer  : Cookham8 
  40.     User      : tfl 
  41.     ---- 
  42.     ---- 
  43.     Domain    : GHI 
  44.     Computer  : Cookham8 
  45.     User      : tfl 
  46.     ---- 
  47. EXAMPLE 
  48.     Shows getting all Value From Remaining Arguments 
  49.     PS C:\foo> .\Get-ParameterAttribute1.ps1 abc def ghi xxx xxx xxx xxx 
  50.     ---- 
  51.     Domain    : abc 
  52.     Compuyter : def 
  53.     User      : ghi xxx xxx xxx xxx 
  54. .PARAMETER Domain 
  55.     A domain name - must be a string 
  56. .PARAMETER Computer 
  57.     A computer Name - must be a string 
  58. .PARAMETER User 
  59.     A user name - must be a string 
  60. #> 
  61. param
  62. [Parameter(Position=0, Mandatory=$true,ValueFromPipeLine=$true)] 
  63. [string] $Domain = "Cookham" ,     
  64. [Parameter(Position=1, Mandatory=$false)] 
  65. [string] $Computer = "Cookham8"
  66. [Parameter(Position=2, Mandatory=$false, ValueFromRemainingArguments=$true)] 
  67. [string] $User     = "tfl"             
  68.  
  69. Process { 
  70. "----" 
  71. "Domain    : {0}" -f $domain 
  72. "Computer  : {0}" -f $computer 
  73. "User      : {0}" -f $user 
  74. "----" 

1 comment:

Bernd Kriszio said...

Hello Thomas,
thanks a lot for this info. I was wondering, how to migrate plain $args to the new syntax.
I just wrote a starter for ISE, which works good, but get-help doesn't use the comment. Code at
http://poshcode.org/774.
By the way which tools do you use to post your listings. It looks really good

Happy scripting
Bernd