The advanced function mimics the behaviour of a regular windows Powershelgl cmdlet.

The cmdletbinding attribute

The  first step in creating an advanced function is to add the [cmdletbinding] attribute to modify the way the function works.

To use the [cmdletbinding] attribute, you place the attribute in a square-bracket attribute tag and include it in the first noncommented line in the function. In addition, the [cmdletbinding] attribute requires the use of the Param keyword. If your advanced function requires no parameters, you can use the Param keyword without specifying any parameters.

function my-function
{
 [cmdletbinding()]
 Param()
}

Without the use of the [cmdletbinding] attribute, you would need to manually change the value of the $VerbosePreference automatic variable from silentlycontinue to continue (and presumably later change it back to the default value). The use of the [cmdletbinding] attribute and Write-Verbose appear here:

function my-function
{
[cmdletbinding()]
Param()
Write-Verbose "verbose stream"
}
Automatic Parameter checks

The default behavior for a Windows PowerShell function is that any additional values beyond the defined number of arguments are supplied to an unnamed argument and are therefore available in the automatic $args variable.

E.g you have a function

function my-function

{

 Param($a)

 $a

}

When the preceding function runs, any value supplied to the -a parameter appears in the output. This appears here:

PS C:\Users\ed.IAMMRED> my-function -a 1,2,3,4

1
2
3
4

If, on the other hand, when calling the function you omit the  first comma, no error is generated— but the output displayed does not meet expectations. This appears here:

PS C:\Users\ed.IAMMRED> my-function -a 1 2,3,4

1

 The remaining parameters appear in the automatic $args variable. you can test it by:

function my-function

{

 Param($a)

 $a

"Rest of the "+$args.count+" args:"

 $args

}

PS C:\Users\ed.IAMMRED> my-function -a 1 2,3,4

1

Rest of the 1 args:

2

3

4

Note that the .count method treat the space as the separator.

The easiest way to identify unhandled parameters supplied to a Windows PowerShell function is to use the [cmdletbinding] attribute. One of the features of the [cmdletbinding] attribute is that it generates an error when unhandled parameter values appear on the command line.

 my-function 1 2 3 4

my-function : A positional parameter cannot be found that accepts argument '3'.

At line:1 char:12

+ my-function <<<<  1 2 3 4

    + CategoryInfo          : InvalidArgument: (:) [my-function], ParameterBindingException

    + FullyQualifiedErrorId : PositionalParameterNotFound,my-function
Add support for Whatif, -confirm parameter

One of the great features of Windows PowerShell is the use of the -whatif parameter on cmdlets that change system state, such as the Stop-Service and Stop-Process cmdlets. If you consistently use the -whatif switched parameter, you can avoid many inadvertent system outages or potential data loss.

1. Inside a function, add the [cmdletbinding()] attribute.

2. Inside the parentheses of the [cmdletbinding] attribute, add SupportsShouldProcess = $true.

3. Add a Param statement.

4. When calling the function, use the -whatif switched parameter.

For example, you want to create a folder:

function my-function
{
 [cmdletbinding(SupportsShouldProcess=$True)]

 Param($path)

 md $path

}

The SupportsShouldProcess attribute turns on both -whatif and -confirm.

If you do not want a cmdlet to execute by default—that is, you wish for it to prompt by default— you add an additional property to the [cmdletbinding] attribute: the con rmimpact property. This technique appears here:

[cmdletbinding(SupportsShouldProcess=$True, confirmimpact="high")]

There values for the confirmimpact property are High, Medium, Low, and None. They correspond to the values for the automatic $confirmpreference variable.

Specify the default parameter set

 

When an advanced function contains multiple parameter sets (or different groupings of parameters for the same cmdlet), the function needs to know which one of several potential possibilities is the default.

For a cmdlet, you can find the default parameter set by this command:

(Get-Command Stop-Process).parametersets | Format-Table name, isdefault -AutoSize

To specify a default parameter set for an advanced function, use the DefaultParameterSetName property of the [cmdletbinding] attribute.

If you want to set the name as the default parameter set, you can use the syntax like this:

[cmdletbinding(DefaultParameterSetName="name")]
The parameter attribute
The mandatory parameter property

By default, all parameters to an advanced function are optional; by using the mandatory prop- erty, you can change that behavior on a parameter-by-parameter basis.

When a function runs with missing mandatory parameters, Windows PowerShell prompts for the missing parameter.

Use of the mandatory parameter appears here:

Function Test-Mandatory

{
 Param(

 [Parameter(mandatory=$true)]

 $name)

 "hello $name"
}

Run the function:

Test-Mandatory

cmdlet Test-Mandatory at command pipeline position 1

Supply values for the following parameters:  # prompt for the missing parameter.

name: Ed Wilson

hello Ed Wilson

If, the user does not supply a value for the missing parameter, but instead skips past the prompt, no error occurs, and the function continues to run, because the user is really assigning something ($null) to the parameter.

The position parameter property

The position parameter property tells Windows PowerShell that the specific parameter receives values when it occupies a specific position. Position numbers are zero based, and therefore the first position is parameter position 0.

By default, Windows PowerShell parameters are positional—that is, you can supply values for them in the order in which they appear in the parameter set.

ParameterSetName property

One of the great benefits of PowerShell V2 Advanced Functions, The ParameterSetName property identifies groups of parameters that taken together create a specific command set.

Note that the same parameter cannot appear in more than one parameter set. Therefore, only the parameters that are unique to each parameter set appear. When creating a parameter set, it is a best practice always to include one mandatory parameter in each set.

Let’s see an example :

Function Test-ParameterSet
{
 Param(
 [Parameter(ParameterSetName="City",Position=0)]
 [string]
 $city,
 [Parameter(ParameterSetName="phone",Position=0)]
 [int]
 $phone)
 Switch ($PSCmdlet.ParameterSetName)
 {
 "city" {"I am from $city"}
 "phone" {"My phone is $Phone"}
 } 
}

PowerShell uses the types of the input to determine which one you want.

You can test by:

PS C:\Windows\system32> Test-ParameterSet 93265432
My phone is 93265432
PS C:\Windows\system32> Test-ParameterSet -Phone 93265432
My phone is 93265432
PS C:\Windows\system32> Test-ParameterSet "Melbourne"
I am from Melbourne
PS C:\Windows\system32> Test-ParameterSet -City "Melbourne"
I am from Melbourne
the ValueFromPipeline property

The ValueFromPipeline property causes Windows PowerShell to accept objects from the pipeline. The entire object passes into the function’s Process block when you use the ValueFromPipeline parameter property. Because the entire object passes to the function, you can access specific properties from the pipeline with dotted notation.

E.g

Function Test-PipedValue
{
Param(
[Parameter(ValueFromPipeline=$true)]
$process)
Process {Write-Host $process.name $process.id}
}

Then you can pipeline  the process into this function :

PS C:\Windows\system32> Get-Process|Test-PipedValue

csrss 424
csrss 496
csrss 4388
dfsrs 1748
dfssvc 2248

...

Instead of receiving an entire object from the pipeline, the ValueFromPipelineByPropertyName property can often simplify code by allowing your function to pick properties from the input object directly from the pipeline.

Function Test-PipedValueByPropertyName
{
Param( [Parameter(ValueFromPipelineByPropertyName=$true)] $processname, [Parameter(ValueFromPipelineByPropertyName=$true)] $id)
Process {Write-Host $processname $id}
}

Then test again with:

PS C:\Windows\system32> Get-Process|Test-PipedValueByPropertyName

csrss 424
csrss 496
csrss 4388
dfsrs 1748
dfssvc 2248
...
the HelpMessage property

The HelpMessage property provides a small amount of help related to a specific parameter. This information becomes accessible when Windows PowerShell prompts for a missing parameter. This means that it only makes sense to use the HelpMessage parameter property when it is coupled with the Mandatory parameter property.

 Function Test-HelpMessage
      {
       Param(
          [Parameter(Mandatory=$true, HelpMessage="Enter your name please")]
          $name)
          "Good to meet you $name"
}