Functions in PowerShell allow you to combine multiple statements and improve the reusability of your code. In this post, you will learn how to scope functions, define parameters, assign data types, and return values.
Profile gravatar of Wolfgang Sommergut

Wolfgang Sommergut

Wolfgang Sommergut has over 20 years of experience in IT journalism. He has also worked as a system administrator and as a tech consultant. Today he runs the German publication WindowsPro.de.
Profile gravatar of Wolfgang Sommergut

If you have worked with VBScript before, the functions in PowerShell might appear familiar. However, it is important to note that major differences exist between Microsoft’s scripting languages.

Whether the function only contains one statement or a complex sequence of commands, you can execute its containing code by calling the function’s name together with the required parameters. This avoids redundant script blocks and facilitates code maintenance.

The use of functions is not required ^

In contrast to most compiled languages, such as C, the use of functions is not required in PowerShell. Thus, your script can contain large parts of code that isn’t encapsulated in any function.

It is worth pointing out that, even though PowerShell is an object-oriented language, functions are defined as in procedural languages and not as methods in classes.

Functions as scope of variables ^

In PowerShell, as in other programming languages, functions define the scope of variables. The values of variables defined within a function block are not available outside the function. However, to avoid undesirable side effects, you should not use the same name for local and global variables.

Scopes also affect the functions themselves. By default, functions that you define in a script are not available at the PowerShell prompt. You can change this by using the scope identifier, as in the example below:

With this command, you are extending the scope of the function Get-UserInput to global, which makes the function available outside the script where you defined it.

Loading functions in the profile ^

If you define a function at the PowerShell prompt to save typing of complex commands, the function only exists during this session. To make it available in future sessions, you have to add it to your PowerShell profile.

In an interactive session, you will probably only use simple functions with just one statement; however, functions can get quite complex in scripts.

The syntax of a function ^

PowerShell help describe the general form of functions as follows:

The definition begins with the keyword function; a declaration of the return value is not provided. As mentioned above, you can prepend the name of the function with a value for the scope. The naming should follow the PowerShell convention in the form verb-noun, as with all integrated PowerShell cmdlets (Get-Process, for instance).

Defining parameters ^

An essential feature of functions is that their statements don’t just have to execute code with constant values; you can also pass changing values as arguments. PowerShell offers many more features here than other languages do, but this also means a steeper learning curve. It is already unusual that two different ways exist to define parameters.

As in most languages, you can define the list of parameters directly after the function name. Alternatively, you can define the parameters at the beginning of the function block with the keyword param.

It is a matter of taste which option you prefer. However, if you intend to use several of the numerous attributes and work with predefined values, you should use the param block to improve the readability of your script.

Named parameters ^

Microsoft’s cmdlets mainly use named parameters. Hence, you should follow this convention for your functions. In the declaration, you define the name of a parameter as a variable, which allows you to access its value in the function.

This example packs the command to run a Windows 8.x app in a function, so that you only have to pass the name of the app (or a part of it) to start it. For instance, if you want to launch the Notepad app, you could call the function in the following way:

Assigning types and values to parameters ^

In the above example, the sole parameter is defined without the use of additional attributes. However, by assigning a data type, you could ensure that the function accepts only a value of the type String.

In most cases, you will want to intercept the function call if no parameter has been passed. You have two options here: You either predefine the value of an argument or you require the use of a particular parameter. You can set a default value in the declaration, like this:

If the function Start-App is called without AppName, Notepad is automatically started. If you want to prevent the function from being called without the parameter AppName, you can use the Mandatory attribute, like this:

This example uses the syntax that defines the parameter with the help of Param within the function. It determines that a value for AppName has to be passed; otherwise, the user will be prompted to enter its value. The function also expects a value of type String.

Validating parameter values ^

In addition to the Mandatory attribute, PowerShell offers a variety of attributes to validate the passed parameters. These include the following:

  • AllowNull
  • AllowEmptyString
  • ValidateCount (specifies the minimum and maximum number of parameter values)
  • ValidateLength (specifies the minimum and maximum number of characters in a parameter)
  • ValidatePattern (specifies a regular expression that is compared to the parameter)

You can find a complete list of the validation options in the PowerShell help under about_Functions_Advanced_Parameters.

Positioning parameters ^

Named parameters make it easier to call a function if you use meaningful names. This is also helped by the fact that the order of the arguments doesn’t matter. However, if you want to work without parameter names, you have to pass them in the exact order that you declared them. Alternatively, you can enforce the position of an argument in the definition of the function.

In this example, the parameter ComputerName always has to be passed at the first position if you call it without an identifier. For instance:

Reading parameter values from $args ^

The easiest use of positional parameters is to read the parameter values from the array $args. The following example calls Test-Connection first with the host name and then with the IP address:

In this case, no validation is taking place. The function MyPing expects the computer name as the first argument ($args[0]) and the IP address as the second argument ($args[1]).

Piping data to functions ^

You don’t have to pass static values to a function via parameters. PowerShell functions also accept input through pipes. Typically, you want to pass the output of a cmdlet or the contents of a file to a function. In the simplest case, you go without the declaration of parameters and read the values from the pipeline by iterating over all objects of the predefined variable $input:

The following example is a variation of Start-App, defined above, except that Get-StartApps (gets the names and AppIDs of apps on the Start screen) isn’t called in the function. Instead, we pipe the output of Get-StartApps into our function:

As of PowerShell 3.0, additional options exist to process the input of a pipe. This includes custom attributes in the declaration and the partition of the function in the begin, process, and end blocks.

Returning values ^

If you have experience with other programming languages, you know that a function returns a value to the calling subroutine. JavaScript and PHP have the return keyword for this purpose; in VBScript, you use a variable with the same name as the one of the function.

PowerShell also knows the return keyword; however, it follows a different logic. In general, the purpose of return is to end the execution of a code section and to give the control back to the parent block.

If you add a parameter to the return statement, the value will indeed be returned to the calling subroutine. However, this also applies for all other statements with an output. This means that any output produced in the function will be stored in the variable together with the return parameter.

If you call the function rTest with the command $r = rTest, the values of $a and $b would be stored in the array as separate elements. Thus, you don’t have to use return to return values from a PowerShell function. In the above example, the result would be the same if you place the variable $b in the line above return and end the function with an empty return.

Take part in our competition and win $100!

Share
0

Related Posts

2 Comments
  1. avatar
    Adam 8 months ago

    Loved discovering about advanced function parameters, thanks for that.

    1+
  2. avatar
    Bilal 1 month ago

    When I define parameter inside a function, this does not work with tab completion. Is there anything wrong in this example code;

    function Get-DJOSInfo {
    [cmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
    param (
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True)]
    [Alias('hostname')]
    [ValidateLength(5,20)]
    [ValidateCount(1,10)]
    [string[]]$computerName,

    [switch]$nameLog
    )

    1+

Leave a reply

Your email address will not be published. Required fields are marked *

*

CONTACT US

Please ask IT administration questions in the forum. Any other messages are welcome.

Sending
© 4sysops 2006 - 2017

Log in with your credentials

or    

Forgot your details?

Create Account