Fun With PowerShell Advanced Functions

Introduction

In my previous post, I covered the use of PowerShell Basic Functions. In this post we’ll cover Advanced Functions.

Advanced Functions provide several abilities over basic ones. First, you can create a detailed parameter list, including the ability to include optional parameters.

Second, you can pipeline enable your functions. Just like a cmdlet, you’ll be able to take input from the pipeline, work with it, then send it out your function back into the pipeline. This will be the subject of our next post.

Finally, you can use features such as Verbose and Debug, which will be the subject of an upcoming blog post.

For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

A Simple Advanced Function

In my Basic Functions post, I created a simple function Get-AValue that multiplied two values together and returned the result. Let’s take a look at the advanced version, Get-BValue.

function Get-BValue()
{
  [CmdletBinding()]
  param (
          [Parameter( Mandatory = $true
                    , HelpMessage = 'Enter value one.'
                    )
          ]
          [int] $one
        , [Parameter( Mandatory = $false
                    , HelpMessage = 'Enter value two.'
                    )
          ]
          [int] $two = 42
        )

  return $one * $two

}

We start with the function keyword, followed by the name we’ve chosen for the function, in this case Get-BValue. Note the parenthesis are empty, unlike a basic function advanced ones declare their parameters in a different spot.

The first line you’ll see in the function is [CmdletBinding()]. This is the indicator to PowerShell that this is an advanced function. It must be included in the first line for PowerShell to treat this as advanced.

Next up are the parameters, inside a param () block. Within we list each parameter, separated by commas.

A useful feature is the ability to add parameter attributes. For the first parameter, $one, we have the following block:

[Parameter( Mandatory = $true
          , HelpMessage = 'Enter value one.'
          )
]

The first attribute is Mandatory. This indicates that this is a required parameter, and can be set to either $true or $false. When $true, if the user does not enter it they will be prompted to supply a value.

The HelpMessage is text that will be displayed when the user gets help on your function. We won’t do much with it in this demo, but I’ve included it to show there are a variety of attributes you can use with parameters.

Next up is the actual parameter declaration, [int] $one. In this demo we’ve strongly typed our variable. Only integer values will be allowed, any string our decimal value (such as 3.14) will be rejected by PowerShell.

Note that for readability I’ve chosen to split the code onto separate lines, you could have condensed all this into a single line if you’d wanted.

Strong typing has its pros and cons. It can be very helpful in cases where the data must be of a specific type. On the other hand, it can prevent other uses. In this demo for example, we could just have easily multiplied a decimal value.

If you want a flexible variable, then you can leave off the type declaration. In this example we’ll leave it in, so you can see how it works.

Next up is the second variable declaration.

, [Parameter( Mandatory = $false
             , HelpMessage = 'Enter value two.'
             )
  ]
  [int] $two = 42

Here, we’ve set Mandatory to $false. This means if the user does not supply a value for $two, it will use the default value. Where does the default value come from?

If you look you’ll see [int] $two = 42. The 42 is the default value, and is used when the user does not supply a value.

After the parameter block ends we have the actual code for the function, in this case a simple return $one * $two.

So let’s see some examples of how this works. In your development environment highlight the function and press F8 (for VSCode) or F5 (for the PowerShell IDE). Now that it’s in memory you can call it.

Get-BValue -one 33 -two 42

Result:
1386

Here I called the function, passing in the parameters by name. I could have also left off the names and called it by position, as we did in the tutorial on basic functions.

Now lets call it only passing in a value for -one.

Get-BValue -one 33

Result:
1386

In this case, it took our input for -one, but since no value for -two was passed in, the function used the default value of 42.

So what happens if we call it and pass in no values?

Get-BValue

Result:
cmdlet Get-BValue at command pipeline position 1
Supply values for the following parameters:
one: 33
1386

As you can see in the Result: output area, we were prompted for a value for one. I entered 33 and hit enter, then got the expected result of 1386.

To illustrate how the strong typing works, let’s call passing in a string for the -one parameter.

Get-BValue -one "x"

Result:
Get-BValue: Cannot process argument transformation on parameter 'one'. Cannot convert value "x" to type "System.Int32". Error: "Input string was not in a correct format."

As you can see, PowerShell rejects our input with the resulting error message.

Conclusion

In this post we got a start in PowerShell Advanced Functions. We covered a simple advanced function, including parameters and how to use attributes with them.

But there’s still more fun to be had! In the next post we’ll see how to pipeline enable your advanced functions. Then in a future post we’ll implement two switches common to all cmdlets and advanced functions, Verbose and Debug.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.