PowerShell cmdlet parameter value tab completion

后端 未结 3 1204
暖寄归人
暖寄归人 2020-12-30 06:40

How do you implement the parameter tab completion for PowerShell functions or cmdlets like Get-Service and Get-Process in PowerShell 3.0?

I realise ValidateSet works

3条回答
  •  感动是毒
    2020-12-30 07:31

    I puzzled over this for a while, because I wanted to do the same thing. I put together something that I'm really happy with.

    You can add ValidateSet attributes from a DynamicParam. Here's an example of where I've generated my ValidateSet on-the-fly from an xml file. See the "ValidateSetAttribute" in the following code:

    function Foo() {
        [CmdletBinding()]
        Param ()
        DynamicParam {
            #
            # The "modules" param
            #
            $modulesAttributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    
            # [parameter(mandatory=...,
            #     ...
            # )]
            $modulesParameterAttribute = new-object System.Management.Automation.ParameterAttribute
            $modulesParameterAttribute.Mandatory = $true
            $modulesParameterAttribute.HelpMessage = "Enter one or more module names, separated by commas"
            $modulesAttributeCollection.Add($modulesParameterAttribute)    
    
            # [ValidateSet[(...)]
            $moduleNames = @()
            foreach($moduleXmlInfo in Select-Xml -Path "C:\Path\to\my\xmlFile.xml" -XPath "//enlistment[@name=""wp""]/module") {
                $moduleNames += $moduleXmlInfo.Node.Attributes["name"].Value
            }
            $modulesValidateSetAttribute = New-Object -type System.Management.Automation.ValidateSetAttribute($moduleNames)
            $modulesAttributeCollection.Add($modulesValidateSetAttribute)
    
            # Remaining boilerplate
            $modulesRuntimeDefinedParam = new-object -Type System.Management.Automation.RuntimeDefinedParameter("modules", [String[]], $modulesAttributeCollection)
    
            $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
            $paramDictionary.Add("modules", $modulesRuntimeDefinedParam)
            return $paramDictionary
        }
        process {
            # Do stuff
        }
    }
    

    With that, I can type

    Foo -modules M
    

    and it will tab-complete "MarcusModule" if that module was in the XML file. Furthermore, I can edit the XML file and the tab-completion behavior will immediately change; you don't have to re-import the function.

提交回复
热议问题