Friday, August 29, 2008

Functions in PowerShell


What's a function?

A function is a script block with a name.  Most functions also take parameters and/or return a value, but that's not required.  The PSDrive called function: has a list of all defined functions, and there will be quite a few in there from the first time you install PowerShell.  You can use Get-Item (or gi, for short) cmdlet to get the Definition property of the function to see how they're made, as shown below.

Function Parameters and the param() Method

Let's make a test function and try this bad boy out.  I'm going to make a function that adds two numbers.  You can use the return statement to explicitly return a value, but any expression that is not assigned to a variable will be sent as output.

function Add-Numbers ($x, $y) {
  $x + $y
}

PS Function:\>  Add-Numbers 23 77
100

Okay, that worked, so let's look at the Definition property:

Function:\>  (gi Add-Numbers).Definition
param($x, $y) $x + $y

That's funny, I don't remember using the param() method in my function.

The param() method is implied when you put your parameters in parentheses before the script block.  This code would do the same thing:

function Add-Numbers {
  param($x, $y)
  $x + $y
}

Command-Line Switches and Named Parameters

So how do we set up named parameters?  We already did.  In PowerShell every variable name that you add to the param() method also is automatically created as a named parameter that you can use at the command-line.  Observe:

Function:\>  Add-Numbers -y 10 -x 20
30

Default Parameter Values

What if you have an optional variable?  Something that usually has the same value, that you'd rather not have to type in every time?   Easy.  Just assign it a value within the param method and you're done.  If you use the parameter when you call the function, then it will take on the value you assign, but if you don't, then it will keep the default value.

function Add-Numbers {
  param($x, $y=20)
  $x + $y
}

Function:\>  Add-Numbers 203
223

A Final Note about Parameters

There are two caveats when calling a function that you should be aware of:
  1. Unnamed parameters are assumed to be in the order that they were declared in param().  If you call Add-Numbers with only one number then it will be assigned to $x because that variable came first.  
  2. Any parameters left over after being assigned to parameters get dumped into an array called $args.

An Example Incorporating What We've Learned

# Get-SmsWmi
# A wrapper for Get-WmiObject that makes it easy to get objects from SMS.
#
# Args:
#   $Class: the WMI class to retrieve
#   $Filter: the where clause of the query
#   $Computername: the SMS server hosting the SMS Provider
#   $Site: the SMS Site Code of the target site
# Returns:
#   An array of WMI objects

function Get-SmsWmi {
  param([string]$Class = $(throw "ERROR: You must enter a class name.`n"), 
        [string]$Filter = $null, 
      [string]$ComputerName = 'sms-server', 
      [string]$Site = 'S00')
  
  [string]$query = "Select * from $Class"
  
  if ($Filter) {
    $query += " Where $Filter"
  }
  
  # Now that we have our parameters, let's execute the command.
  gwmi -ComputerName $ComputerName -Namespace ('root\sms\site_' + $Site) -Query $query
}

No comments: