Is there a Module or Something Similar for Interactive Prompts in PowerShell?

时间:2019-04-17 00:39:51

标签: powershell user-interface prompt

Is there something we can use in PowerShell to ask users to select one item from an array of items? For example, I like how Inquirer.js can do it.

enter image description here

I have also seen PoshGui, but it seems too much work to create just a simple prompt.

The reason we want something similar is that we need to provide deployment scripts for our clients and make deployment guides as easy as possible. Asking users to select one item on a screen is much better than asking them to insert some guid to a config file.

Do you have any suggestions for user prompts for arrays?

5 个答案:

答案 0 :(得分:1)

I've used the Out-GridView cmdlet for this in the past. When used with the -PassThru switch it allows the selected item to be passed to a variable. The example image you've shown, when written using Out-GridView (ogv if you want to use the alias) is:

$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"
}

There are many considerations to take into account with this, the windows might not appear where you want them to and they may appear behind others. Also, this is a very simple example that obviously needs error handling and other aspects built in. I'd suggest some testing or to get a second opinion from others on SO.

答案 1 :(得分:1)

您当然可以发挥自己的创造力。 这是一个构建控制台菜单的小功能:

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
    }
}

结果:

main menu

side menu

答案 2 :(得分:1)

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

可能提供专用的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 '&')"

这会产生类似的内容:

enter image description here

答案 3 :(得分:1)

您也可以尝试const hrefs = await page.$$eval('li.product-item > a.product-image', elements => elements.map(el => el.href)) const urls = hrefs.map(el => siteUrl + el) for (const url of urls) { await page.goto(url) await page.screenshot({ path: url + '.png' }) } 模块: https://www.powershellgallery.com/packages/ps-menu

示例:

enter image description here

答案 4 :(得分:0)

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

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

$selectedItem = Get-FormArrayItem (Get-ChildItem)

enter image description here

$Delete = Get-FormBinaryAnswer "Delete file?"

enter image description here

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

enter image description here

# -------------------------------------------------------------------------------
# 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"

enter image description here