PowerShell for Programmers: How to write a function the right way

Kory Thacher

Just like I mentioned in my first post, PowerShell supports a lot of stuff that makes it pretty easy to dive in and get stuff running. The following two examples are supported in PowerShell, but not something you should really be doing for any reusable tool set.

Function MyFunction ($P1, $P2)
{
Write-host $p1 -foregroundcolor cyan
Write-host $p2 -foregroundcolor Magenta
}

MyFunction -P1 "hello" -p2 "world"

Function MyFunction
{
Write-host $args[0] -foregroundcolor cyan
Write-host $args[1] -foregroundcolor Magenta
}

MyFunction "hello" "world"

Putting your parameters (arguments) next to the function name in parenthesis is pretty standard in most languages, but in PowerShell it will limit your functionality. Similarly, $args will stop working for you if you add some of those more useful features, but I’ll show you a way to mimic the functionality on your own later.

So, how should you be writing your functions? With the param() keyword:

Function MyFunction
{
param($P1, $P2)
Write-host $p1 -foregroundcolor cyan
Write-host $p2 -foregroundcolor Magenta
}

 

For super basic stuff, this won’t make a big difference, but for adding attributes (such as common parameters, mandatory parameters, etc) we need to use the later version.

Get in the habit of using param() every time.

“Wait, shouldn’t they already be mandatory?”

Not in PowerShell. Let’s take a look at the syntax:

get-command myfunction -Syntax

 

Myfunction [[-p1] <object>] [[-p2] <object>]

Unlike most languages, by default everything is:

  1. optional
  2. positional
  3. assigned the generic object type

I’ll walk you through how we can change some of that stuff and get functions more like what we are used to, and I’ll follow up in a later post with more details on what we can do with advanced functions.

Strong Typing

Strongly typing parameters will assign them a data type other than object in the syntax, and provide the same auto-conversion or erroring we saw in the variables section.

Function Myfunction2
{
param([int]$p1, [int]$p2)
"p1 is $p1"
"p2 is $p2"
}

get-command myfunction -Syntax

Myfunction2 5.5 2.5

Myfunction2 "fred" 4

 

Default Values

Assigning default values for parameter is easy in PowerShell. If you want something to essentially be mandatory, but have a default value if nothing else is specified we can assign it right in the param() statement.

 

Function Myfunction3
{
param([int]$p1=2, [int]$p2=5)
"p1 is $p1"
"p2 is $p2"
}

Myfunction3 1 2
Myfunction3 -p2 2
Myfunction3

Mandatory Parameters

If you want “normal” mandatory parameters, we can accomplish this through .NET attributes. We’ll learn about some more attributes later, but if things being optional is frustrating you right now, here is how to flag it as mandatory. Notice in PowerShell the mandatory flags will prompt the user when using it interactively instead of just failing. We’ll just make $p1 mandatory here:

 

Function Myfunction4
{
param([parameter(Mandatory)][int]$p1,
[int]$p2=5)
"p1 is $p1"
"p2 is $p2"
}

Get-command myfunction4 -syntax

Myfunction4 1 2
Myfunction4 -p2 2
Myfunction4

 

Well that’s all for now, hopefully this helps you get going on your PowerShell journey and clear up why functions might look and behave a bit differently than you’re used to. In my next post I’ll show some more attributes we can use to build out these advanced functions and have them behave like cmdlets.

For the main series post, check back here.

If you find this helpful don’t forget to rate, comment and share 🙂

0 comments

Discussion is closed.

Feedback usabilla icon