none
Parameter Auto Complete RRS feed

  • Вопрос

  • В PS 3 появилась возможность автоподстановки значений параметров. Например Get-Process подставляет по Tab имена процессов. Для своих командлетов можно использовать ValidateSet в определении параметра, но только статически заданными значениями. Еще вроде работало задание типа параметра посредством типов Enum.

    Для задания динамического списка возможных значений параметра (как у Get-Process) можно было использовать Dynamic Parameters. Получается довольно наворочено.

    А в более поздних версиях PS что-то в этом плане поменялось? Есть способ реализовать автоподстановку более просто?


    Сазонов Илья

    https://isazonov.wordpress.com/


    7 сентября 2016 г. 14:03
    Модератор

Ответы

  • function Get-Test
    {
        [CmdletBinding()]
        Param
        (
            [Parameter(Mandatory=$true)]
            [ArgumentCompleter({
                param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)
                Get-Process |
                Group-Object Name |
                Where-Object Name -like $WordToComplete* |
                Sort-Object Name | 
                ForEach-Object {
                    [System.Management.Automation.CompletionResult]::new(
                        $_.Name,
                        "$($_.Name)$(if($_.Group.Count -gt 1) {" ($($_.Group.Count))"})",
                        'ParameterValue',
                        "Процесс $($_.Name), количество $($_.Group.Count) шт."
                    )
                }
            })]
            $Param1
        )
    }
    • Помечено в качестве ответа KazunEditor 13 сентября 2016 г. 11:30
    8 сентября 2016 г. 4:51

Все ответы

  • Поставляется модуль PsReadLine:

    PS (STA) > Get-Service [Ctrl+Space]
    Display all 218 possibilities? (y or n)

    PS (STA) > [Environment]::[Ctrl+Space]

    CommandLine                 NewLine                     UserInteractive             GetCommandLineArgs
    CurrentDirectory            OSVersion                   UserName                    GetEnvironmentVariable
    CurrentManagedThreadId      ProcessorCount              Version                     GetEnvironmentVariables
    ExitCode                    StackTrace                  WorkingSet                  GetFolderPath

    PS (STA) > (Get-Item).[Ctrl+Space]

    7 сентября 2016 г. 14:26
    Отвечающий
  • Вопрос про написание собственного командлета, у которого параметр будет поддерживать автоподстановку. Например, хорошо было бы "ValidateSet теперь поддерживает скрипт блок"

    Сазонов Илья

    https://isazonov.wordpress.com/


    7 сентября 2016 г. 14:35
    Модератор
  • Если модуль PsReadLine не загружен, tab осуществляется функцией ${function:TabExpansion2} , которая парсит ast. Поэтому ее и следуется дополнять для парсинга командлета.

    Зачем ValidateSet поддерживать scriptblock, когда есть ValidateScript?

    В PS 5 доступен командлет Register-ArgumentCompleter.

    Примеры можно посмотреть - http://stackoverflow.com/questions/12291199/example-showing-how-to-override-tabexpansion2-in-windows-powershell-3-0

     
    • Изменено KazunEditor 7 сентября 2016 г. 16:04
    7 сентября 2016 г. 15:36
    Отвечающий
  • Если мне не изменяет память, то данная возможность появилась в PS v2. Ну а начиная с PS v5 можно делать так.
    7 сентября 2016 г. 16:00
  • Вот пример

    function Get-Test
    {
        [CmdletBinding()]
        [Alias()]
        [OutputType([String])]
        Param
        (
            # Param1 help description
            [Parameter(Mandatory=$true 
    )]
            [ValidateNotNull()]
            [ValidateNotNullOrEmpty()]
            [ValidateCount(0,5)]
            [ValidateSet("sun", "moon", "earth")]
            [Alias("p1")] 
            $Param1
        )
        {}
    }
    
     

    Значения "sun", "moon", "earth" подставляются по Tab (загружен PsReadLine). Мой вопрос: можно ли так же просто сделать подстановку, например, имен текущих процессов

    [ValidateSet({(Get-Process).Name})]

    или только путями описанными выше?


    Сазонов Илья

    https://isazonov.wordpress.com/

    8 сентября 2016 г. 3:29
    Модератор
  • function Get-Test
    {
        [CmdletBinding()]
        Param
        (
            [Parameter(Mandatory=$true)]
            [ArgumentCompleter({
                param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)
                Get-Process |
                Group-Object Name |
                Where-Object Name -like $WordToComplete* |
                Sort-Object Name | 
                ForEach-Object {
                    [System.Management.Automation.CompletionResult]::new(
                        $_.Name,
                        "$($_.Name)$(if($_.Group.Count -gt 1) {" ($($_.Group.Count))"})",
                        'ParameterValue',
                        "Процесс $($_.Name), количество $($_.Group.Count) шт."
                    )
                }
            })]
            $Param1
        )
    }
    • Помечено в качестве ответа KazunEditor 13 сентября 2016 г. 11:30
    8 сентября 2016 г. 4:51
  • Да про это и вопрос был. :-)

    Этот ArgumentCompleter еще не документирован?


    Сазонов Илья

    https://isazonov.wordpress.com/

    8 сентября 2016 г. 5:20
    Модератор
  • Когда я последний раз проверял, документации не было. Возможно кометарии из исходного кода будут Вам полезны.
    8 сентября 2016 г. 18:14
  • Спасибо, было полезно.

    Сазонов Илья

    https://isazonov.wordpress.com/

    13 сентября 2016 г. 11:54
    Модератор