Working with Functions in Windows PowerShell

  • 11/11/2015

Using functions to provide ease of code reuse

When scripts are written using well-designed functions, it makes it easier to reuse them in other scripts, and to provide access to these functions from within the Windows PowerShell console. To get access to these functions, you will need to dot-source the containing script by placing a dot in front of the path to the script when you call it, and put the functions in a module or load them via the profile. An issue with dot-sourcing scripts to bring in functions is that often the scripts might contain global variables or other items you do not want to bring into your current environment.

An example of a useful function is the ConvertToMeters.ps1 script because it converts feet to meters. There are no variables defined outside the function, and the function itself does not use the Write-Host cmdlet to break up the pipeline. The results of the conversion will be returned directly to the calling code. The only problem with the ConvertToMeters.ps1 script is that when it is dot-sourced into the Windows PowerShell console, it runs and returns the data because all executable code in the script is executed. The ConvertToMeters.ps1 script is shown here.

ConvertToMeters.ps1

Function Script:ConvertToMeters($feet)
{
  "$feet feet equals $($feet*.31) meters"
} #end ConvertToMeters
$feet = 5
ConvertToMeters -Feet $feet

With well-written functions, it is trivial to collect them into a single script—you just cut and paste. When you are done, you have created a function library.

When pasting your functions into the function library script, pay attention to the comments at the end of the function. The comments at the closing brace for each function not only point to the end of the script block, they also provide a nice visual indicator for the end of each function. This can be helpful when you need to troubleshoot a script. An example of such a function library is the ConversionFunctions.ps1 script, which is shown here.

ConversionFunctions.ps1

Function Script:ConvertToMeters($feet)
{
  "$feet feet equals $($feet*.31) meters"
} #end ConvertToMeters

Function Script:ConvertToFeet($meters)
{
 "$meters meters equals $($meters * 3.28) feet"
} #end ConvertToFeet

Function Script:ConvertToFahrenheit($celsius)
{
 "$celsius celsius equals $((1.8 * $celsius) + 32 ) fahrenheit"
} #end ConvertToFahrenheit

Function Script:ConvertTocelsius($fahrenheit)
{
 "$fahrenheit fahrenheit equals $( (($fahrenheit - 32)/9)*5 ) celsius"
} #end ConvertTocelsius

Function Script:ConvertToMiles($kilometer)
{
  "$kilometer kilometers equals $( ($kilometer *.6211) ) miles"
} #end convertToMiles

Function Script:ConvertToKilometers($miles)
{
  "$miles miles equals $( ($miles * 1.61) ) kilometers"
} #end convertToKilometers

One way to use the functions from the ConversionFunctions.ps1 script is to use the dot-sourcing operator to run the script so that the functions from the script are part of the calling scope. To dot-source the script, you use the dot-source operator (the period, or dot symbol), followed by a space, followed by the path to the script containing the functions you want to include in your current scope. (Dot-sourcing is covered in more depth in the following section.) After you do this, you can call the function directly, as shown here.

PS C:\> . C:\scripts\ConversionFunctions.ps1
PS C:\> convertToMiles 6
6 kilometers equals 3.7266 miles

All of the functions from the dot-sourced script are available to the current session. This can be demonstrated by creating a listing of the function drive, as shown here.

PS C:\> dir function: | Where { $_.name -like 'conv*'} |
Format-Table -Property name, definition -AutoSize

Name                Definition
----                ----------
ConvertToMeters     param($feet) "$feet feet equals $($feet*.31) meters"...
ConvertToFeet       param($meters) "$meters meters equals $($meters * 3.28) feet"...
ConvertToFahrenheit param($celsius) "$celsius celsius equals $((1.8 * $celsius) + 32 )
fahrenheit"...
ConvertTocelsius    param($fahrenheit) "$fahrenheit fahrenheit equals $( (($fahrenheit -
32)/9)*5 ) celsius...
ConvertToMiles      param($kilometer) "$kilometer kilometers equals $( ($kilometer *.6211) )
miles"...
ConvertToKilometers param($miles) "$miles miles equals $( ($miles * 1.61) ) kilometers"...