Creating Parameters with Dynamic IntelliSense

by Jul 28, 2016

PowerShell 3+

Today, we dive a little deeper in the programming part, and show you how a PowerShell function can have parameters that have dynamic intelliSense completion.

The goal is to define a function called “Manage-Service” with the –Service parameter, and when you enter this parameter, the PowerShell ISE IntelliSense should display the names of all currently running services, so you can easily select one.

Here is how this can be done:

function Manage-Service
{
  param
  (
    [Parameter(Mandatory)]
    [ValidateSet('Stop','Suspend')]
    $Action
  )
  dynamicparam
  {
    # dynamically add a new parameter called -Service
    # with a ValidateSet that contains all currently
    # running services
    $Bucket = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
    
    $AttributeList = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
    $Values = Get-Service | Where-Object { $_.Status -eq 'Running' } | Select-Object -ExpandProperty DisplayName
    $AttribValidateSet = New-Object System.Management.Automation.ValidateSetAttribute($Values)
    $AttributeList.Add($AttribValidateSet)
    
    $AttribParameter = New-Object System.Management.Automation.ParameterAttribute
    $AttribParameter.Mandatory = $true
    $AttributeList.Add($AttribParameter)
    $ParameterName = 'Service'
    $Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName,[String], $AttributeList)
    $Bucket.Add($ParameterName, $Parameter)
    $Bucket
  }
  end
  {
    # Important: Make sure dynamic parameters are
    # available. They only exist in $PSBoundParameters
    # and need to be manually transferred to a variable
    Foreach ($key in $PSBoundParameters.Keys)
    {
      if ($MyInvocation.MyCommand.Parameters.$key.isDynamic)
      {
        Set-Variable -Name $key -Value $PSBoundParameters.$key
      }
    }
    
    Switch($Action)
    {
      'Stop'     { Stop-Service $Service -WhatIf}
      'Suspend'  { Suspend-Service $Service -WhatIf}
    }
  }
}

Key is the “dynamicparam” section which can define “dynamic parameter” during runtime. Obviously, defining a parameter programmatically is not much fun, but it works. In the example, take a look at $Values: this is the variable that holds the list of allowed values for the parameter.

Note also that dynamic parameters deliver their values to the function inside of $PSBoundParameters only. That’s why the sample code reads all dynamic parameters from that variable, and turns them into easily usable variables.

Twitter This Tip! ReTweet this Tip!