【问题标题】:Is there a Module or Something Similar for Interactive Prompts in PowerShell?PowerShell 中是否有用于交互式提示的模块或类似的东西?
【发布时间】:2019-04-17 00:39:51
【问题描述】:

我们可以在 PowerShell 中使用什么东西来要求用户从一组项目中选择一个项目吗?例如,我喜欢Inquirer.js 如何做到这一点。

我也见过PoshGui,但创建一个简单的提示似乎工作量太大。

我们想要类似的东西的原因是我们需要为我们的客户提供部署脚本并使部署指南尽可能简单。要求用户在屏幕上选择一项比要求他们将一些 guid 插入配置文件要好得多。

您对数组的用户提示有什么建议吗?

【问题讨论】:

标签: powershell user-interface prompt


【解决方案1】:

你也可以试试ps-menu 模块: https://www.powershellgallery.com/packages/ps-menu

示例:

【讨论】:

    【解决方案2】:

    我过去曾为此使用过Out-GridView cmdlet。当与-PassThru 开关一起使用时,它允许将所选项目传递给变量。使用Out-GridView(如果您想使用别名,则为ogv)编写时显示的示例图像是:

    $task = Read-Host -Prompt "What do you want to do?"
    
    if ($task -eq "Order a pizza") {
      $pizza_sizes = @('Jumbo','Large','Standard','Medium','Small','Micro')
      $size = $pizza_sizes | Out-GridView -Title "What size do you need?"  -PassThru
      Write-Host "You have selected $size"
    }
    

    对此有许多考虑因素,窗口可能不会出现在您希望它们出现的位置,它们可能会出现在其他窗口的后面。此外,这是一个非常简单的示例,显然需要内置错误处理和其他方面。我建议进行一些测试或从其他人那里获得关于 SO 的第二意见。

    【讨论】:

    • 如果显示一个 GUI 对话框是可以接受的,那当然是一种简单的实现方式。请注意,选择似乎仅适用于箭头键和 Home/End。 -PassThru对应-OutputMode Multiple,所以最好使用-OutputMode Single
    【解决方案3】:

    当然,您可以随心所欲地发挥创造力.. 这是一个构建控制台菜单的小函数:

    function Simple-Menu {
        Param(
            [Parameter(Position=0, Mandatory=$True)]
            [string[]]$MenuItems,
            [string] $Title
        )
    
        $header = $null
        if (![string]::IsNullOrWhiteSpace($Title)) {
            $len = [math]::Max(($MenuItems | Measure-Object -Maximum -Property Length).Maximum, $Title.Length)
            $header = '{0}{1}{2}' -f $Title, [Environment]::NewLine, ('-' * $len)
        }
    
        # possible choices: didits 1 to 9, characters A to Z
        $choices = (49..57) + (65..90) | ForEach-Object { [char]$_ }
        $i = 0
        $items = ($MenuItems | ForEach-Object { '[{0}]  {1}' -f $choices[$i++], $_ }) -join [Environment]::NewLine
    
        # display the menu and return the chosen option
        while ($true) {
            cls
            if ($header) { Write-Host $header -ForegroundColor Yellow }
            Write-Host $items
            Write-Host
    
            $answer = (Read-Host -Prompt 'Please make your choice').ToUpper()
            $index  = $choices.IndexOf($answer[0])
    
            if ($index -ge 0 -and $index -lt $MenuItems.Count) {
                return $MenuItems[$index]
            }
            else {
                Write-Warning "Invalid choice.. Please try again."
                Start-Sleep -Seconds 2
            }
        }
    }
    

    你可以像下面这样使用它:

    $menu = 'Pizza', 'Steak', 'French Fries', 'Quit'
    $eatThis = Simple-Menu -MenuItems $menu -Title "What would you like to eat?"
    switch ($eatThis) {
        'Pizza' {
            $menu = 'Jumbo', 'Large', 'Standard', 'Medium', 'Small', 'Micro'
            $eatThat = Simple-Menu -MenuItems $menu -Title "What size do you need?"
            Write-Host "`r`nEnjoy your $eatThat $eatThis!`r`n" -ForegroundColor Green
        }
        'Steak' {
            $menu = 'Well-done', 'Medium', 'Rare', 'Bloody', 'Raw'
            $eatThat = Simple-Menu -MenuItems $menu -Title "How would you like it cooked?"
            Write-Host "`r`nEnjoy your $eatThat $eatThis!`r`n" -ForegroundColor Green
        }
        'French fries' {
            $menu = 'Mayonaise', 'Ketchup', 'Satay Sauce', 'Piccalilly'
            $eatThat = Simple-Menu -MenuItems $menu -Title "What would you like on top?"
            Write-Host "`r`nEnjoy your $eatThis with $eatThat!`r`n" -ForegroundColor Green
        }
    }
    

    结果:

    【讨论】:

      【解决方案4】:

      不幸的是,内置的东西很少,而且很难发现 - 见下文。

      可能提供专用的Read-Choice cmdlet 或增强Read-Host is being discussed on GitHub

      $host.ui.PromptForChoice() 方法支持显示选择菜单,但有局限性:

      • 选项显示在单行(可能换行)。

      • 仅支持单字符选择器。

      • 选择符必须是菜单项文本的一部分。

      • 提交选择始终需要按Enter

      • 始终提供? 选项,即使您不想/不需要为每个菜单项提供解释性文本。

      这是一个例子:

      # The list of choices to present.
      # Specfiying a selector char. explicitly is mandatory; preceded it by '&'.
      # Automating that process while avoiding duplicates requires significantly
      # more effort.
      # If you wanted to include an explanation for each item, selectable with "?",
      # you'd have to create each choice with something like:
      #   [System.Management.Automation.Host.ChoiceDescription]::new("&Jumbo", "16`" pie")
      $choices = '&Jumbo', '&Large', '&Standard', '&Medium', 'Sma&ll', 'M&icro'
      
      # Prompt the user, who must type a selector character and press ENTER.
      # * Each choice label is preceded by its selector enclosed in [...]; e.g.,
      #   '&Jumbo' -> '[J] Jumbo'
      # * The last argument - 0 here - specifies the default index.
      #   * The default choice selector is printed in *yellow*.
      #   * Use -1 to indicate that no default should be provided
      #     (preventing empty/blank input).
      # * An invalid choice typed by the user causes the prompt to be 
      #   redisplayed (without a warning or error message).
      $index = $host.ui.PromptForChoice("Choose a Size", "Type an index and press ENTER:", $choices, 0)
      
      "You chose: $($choices[$index] -replace '&')"
      

      这会产生类似:

      【讨论】:

        【解决方案5】:

        所有答案都是正确的,但我也写了一些可重复使用的PowerShell helper functionsReadme。我自动生成基本的 WinForms。看起来很丑,但是很管用。

        https://github.com/Zerg00s/powershell-forms

        $selectedItem = Get-FormArrayItem (Get-ChildItem)
        

        $Delete = Get-FormBinaryAnswer "Delete file?"
        

        $newFileName = Get-FormStringInput "Enter new file name" -defaultValue "My new file"
        

        # -------------------------------------------------------------------------------
        # Prepare the list of inputs that user needs to populate using an interactive form    
        # -------------------------------------------------------------------------------
        $preDeployInputs = @{
            suffix                       = ""
            SPSiteUrl                    = "https://ENTER_SHAREPOINT_SITE.sharepoint.com"
            TimeZone                     = "Central Standard Time"
            sendGridRegistrationEmail    = "ENTER_VALID_EMAIL_ADDRESS"
            sendGridRegistrationPassword = $sendGridPassword
            sendGridRegistrationCompany  = "Contoso & Tailspin"
            sendGridRegistrationWebsite  = "https://www.company.com"
            fromEmail                    = "no-reply@DOMAIN.COM"
        }
        
        $preDeployInputs = Get-FormItemProperties -item $preDeployInputs -dialogTitle "Fill these required fields"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-13
          • 2017-12-08
          • 1970-01-01
          • 2011-12-04
          • 2011-01-07
          • 1970-01-01
          相关资源
          最近更新 更多