Home Technology Argument Completion in PowerShell 3.0

Argument Completion in PowerShell 3.0

PowerShell 2.0 supported autocompletion for commands and parameters. In PowerShell 3.0, you can now also autocomplete arguments (values for parameters). In this article, we’d like to illustrate which types of arguments can be autocompleted, and what you need to do to make your own functions compatible to this new feature.

Autocompleting Arguments

Gone are the times where you needed to type in values for parameters or guess which values were valid. Many parameters now support autocompletion. Check out the following lines, and press TAB where indicated:

Get-ChildItem -Pa<TAB>
Get-ChildItem -Path c:\Win<TAB>
Get-ChildItem -Path c:\Windows -Fi<TAB>
Get-ChildItem -Path c:\Windows -Filter *.ps1 -R<TAB>
Get-ChildItem -Path c:\Windows -Filter *.ps1 -Recurse -Errora<TAB>
Get-ChildItem -Path c:\Windows -Filter *.ps1 -Recurse -ErrorAction <TAB>
Get-ChildItem -Path c:\Windows -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue

Autocompletion now works for commands (such as Get-ChildItem), for parameters (such as -Path or -Recurse), and for parameter content, such as after -Path or after -ErrorAction.

While there was autocompletion support for paths in PowerShell 2.0, the new PowerShell 3.0 now also completes other types of values, such as the ErrorAction values to control how cmdlets deal with errors. Argument completion works in a lot of scenarios:

Many parameters support argument completion

Argument completion in action

When Argument Completion Fails

Argument completion still seems to fail in some cases. For example, in the following scenario, there is no autocompletion for the parameter -ComputerName:

Get-Process -ComputerName <TAB>

Well, actually you do get autocompletion, but PowerShell suggests file system paths which is of course the wrong thing at this point. Why is it that PowerShell 3.0 can autocomplete arguments perfectly well in some parameters and fails in others?

The reason is simple: to autocomplete a parameter, PowerShell needs to know what the parameter expects. Whenever a parameter is not typed (not assigned a specific type) and/or the type assigned to a parameter is not a list of choices, then PowerShell automatically falls back to simple path completion.

The parameter -ComputerName in the previous example expects a string (text). It can be any computer, there is no valid list of computer names. That’s why there is no specific autocompletion for it.

Supporting Argument Completion

To support argument completion in your own functions, you just need to make sure that PowerShell “knows” what values the parameter expects. Traditionally, you would do this by assigning an enumeration type like in this example:

function Select-Color

    "You selected: $Color"

When you run this function and then use it, PowerShell 3.0 discovers that the parameter -Color expects the type System.ConsoleColor, and thus autocompletion can offer the correct list of valid values:

Functions need to assign enumeration types to parameters

Functions need to assign enumeration types to parameters

As you see, autocompletion correctly suggests all valid console colors.

Unfortunately, there isn’t always a type that describes correctly what a parameter wants from the user. And it would be an overkill to define and compile a new enumeration type just to make autocompletion work.

That’s why there is an easy alternative: just add a ValidateSet attribute to your parameter. It declares the list of valid values. In PowerShell 2.0, this attribute merely checked whether the user submitted the right value. In PowerShell 3.0, the attribute is also picked up by the autocompletion engine. Have a look at this function:

function Select-City
        [ValidateSet('New York','Redmond','Hanover','Tokio')]

    "You selected: $City"

There is no type that enumerates city names. The parameter -City is therefore decorated with a ValidateSet attribute that defines the list of cities. Now, PowerShell 3.0 knows exactly which cities the parameter accepts. Thus, argument completion works like a charm:

ValidateSet lists turn into argument completion

ValidateSet lists turn into argument completion

So to make your own functions fully compatible with PowerShell 3.0 and provide rich Intellisense to your users, make sure your parameters are typed correctly. If a type is not sufficient (or available) to describe what your parameter needs, add a ValidateSet and explicitly list the valid values.