Categories

Advanced Functions part 1

Advanced functions are one of the major new features of PowerShell. They enable functions written in PowerShell to behave in the same way as cmdlets especially in the way they work on the pipeline.

However when you look at the help files

PS> get-help about*functions* | select Name

Name
----
about_functions
about_functions_advanced
about_functions_advanced_methods
about_functions_advanced_parameters
about_functions_cmdletbindingattribute

 

There is a lot of information to understand.  In this short series of posts I will explain how the various methods and parameters can be used to provide a lot of functionality for the absolute minimum of code.  As an example consider this simple function

 

001
002
003
004
005
006
007
function fone {
param (
    [int]$a,
    [int]$b
)   
    $a + $b
}

 

It takes two integers and returns the result.

As an aside I always put a type on the parameters, if at all possible, as it prevents errors that can occur by attempting to input the wrong data type

PS> fone 1 "a"
fone : Cannot process argument transformation on parameter 'b'. Cannot convert value "a" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:5
+ fone <<<<  1 "a"
    + CategoryInfo          : InvalidData: (:) [fone], ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,fone

 

I always use put the parameters in a param block inside the function – its a consistency of style that helps me.

This function will work in PowerShell v1.

We can use the function

PS> fone 1 2
3

and everything works OK. But we can also perform this action

PS> fone 1
1

which may be OK in this example but in other functions could lead to problems.  In PowerShell v1 we would do something like this

001
002
003
004
005
006
007
008
009
010
011
012
function ftwo {
param (
    [int]$a,
    [int]$b
)   
    if (($a -eq 0) -or ($b -eq 0)) {
        Throw "both parameters must be given"
    }
    else {
        $a + $b
    }
}

 

PS> ftwo 1 2
3

PS> ftwo 1
both parameters must be given
At line:7 char:14
+         Throw <<<<  "both parameters must be given"
    + CategoryInfo          : OperationStopped: (both parameters must be given:String) [], RuntimeException
    + FullyQualifiedErrorId : both parameters must be given

BUT what do we do if we want one of the values to be zero!

In PowerShell v2 we can make the parameters mandatory ie you have to supply them.  All we have to do is add the statement [parameter(Mandatory=$true)] to our parameter definition.

001
002
003
004
005
006
007
008
009
010
function fthree {
param (
    [parameter(Mandatory=$true)]
    [int]$a,
   
    [parameter(Mandatory=$true)]
    [int]$b
)   
    $a + $b
}

 

PS> fthree 1 2
3

Supplying two parameters works fine.  If we only supply one parameter we are prompted for the other

PS> fthree 1

cmdlet fthree at command pipeline position 1
Supply values for the following parameters:
b: 2
3

and we can handle zeros

PS> fthree 1 0
1

One simple statement gives us a lot of power.

One thing to be aware of is that if you make a parameter mandatory any default values are ignored i.e. the mandatory check overrides the default.

Having seen an example of what we can do with advanced functions we’ll look at the whole structure of functions in the next post

Leave a Reply