PowerShell中是否有交互式提示的模块或类似内容?

问题描述 投票:3回答:3

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

enter image description here

我也看过PoshGui,但创建一个简单的提示似乎太多了。

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

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

powershell user-interface prompt
3个回答
1
投票

我过去曾经使用过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上获得其他人的第二意见。


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


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


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                    = "[email protected]"
}

$preDeployInputs = Get-FormItemProperties -item $preDeployInputs -dialogTitle "Fill these required fields"

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.