views:

81

answers:

2

I don't remember ever being prompted for multiple selections before in PowerShell, but I've seen several examples of hosts implementing this interface. Unfortunately, those are the only references I've seen to the interface. I've never seen "here's how to test that you're implementing it correctly".

+2  A: 

For example: the command Remove-Item C:\TEMP\Test prompts you to choose:

Confirm
The item at C:\TEMP\Test has children and the Recurse parameter was not specified. If you continue, all children will be removed with the item. Are you sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):

Or you can build your own call using this script (or its idea): Get-Choice.ps1 - Displays PowerShell style menu and gets a user choice

Roman Kuzmin
Nice blog post. Too bad that functionality isn't exposed via Read-Host.
Keith Hill
The method in the interface I'm asking about returns a collection of choices. This example looks like a standard "select one from a list" prompt.
Mike Shepard
The interface IHostUISupportsMultipleChoiceSelection from the question has the only method `PromptForChoice` which is shown in my example. See also: http://msdn.microsoft.com/en-us/library/system.management.automation.host.ihostuisupportsmultiplechoiceselection_members
Roman Kuzmin
I did not see a host that returns 2+ choices and provides some UI for this. I am not sure why this method returns a collection. A design flaw is quite possible.
Roman Kuzmin
Aha, in remarks to IHostUISupportsMultipleChoiceSelection (same MSDN link) I can see this: “It is up to each host application to implement this interface. To provide a set of choices where the user can select *only one option*, see…”. Still, in my opinion, such a design is not perfect because it does not have an option to distinguish single/multi but it is kind of designed for both.
Roman Kuzmin
Here's the link for the PromptForChoice method that returns a collection of integers. http://msdn.microsoft.com/en-us/library/system.management.automation.host.ihostuisupportsmultiplechoiceselection.promptforchoice It has a slightly different signature than the PromptForChoice function defined in the PSHostUserInterface class (it has a single int as the default choice vs. the other function that has a collection of ints as the default choices).
Mike Shepard
I'm going to go ahead and accept your answer. Thanks for putting the effort into looking at this. I'm pretty sure this is really an edge case, since I can't find any examples that use it.
Mike Shepard
+1  A: 

Please, disregard my first answer; it is not an answer at all, as I can see now. And thank you for a really interesting question.

I still do not know cmdlets that use that interface. But we can use it on our own from scripts. Let's modify the mentioned Get-Choice.ps1 and call the new one Get-Choice2.ps1:

<#
.SYNOPSIS
    Displays PowerShell style menu and gets user choices

.DESCRIPTION
    *) Returns choice indexes.
    *) Choice keys are indicated by '&' in menu items.
    *) Help strings can be empty or nulls (items are used themselves).
#>

param
(
    # Menu caption
    [string]$Caption = 'Confirm',
    # Menu message
    [string]$Message = 'Are you sure you want to continue?',
    # Choice info pairs: item1, help1, item2, help2, ...
    [string[]]$Choices = ('&Yes', 'Continue', '&No', 'Stop'),
    # Default choice indexes (i.e. selected on [Enter])
    [int[]]$DefaultChoice = @(0)
)
if ($args) { throw "Unknown parameters: $args" }
if ($Choices.Count % 2) { throw "Choice count must be even." }

$descriptions = @()
for($i = 0; $i -lt $Choices.Count; $i += 2) {
    $c = [System.Management.Automation.Host.ChoiceDescription]$Choices[$i]
    $c.HelpMessage = $Choices[$i + 1]
    if (!$c.HelpMessage) {
        $c.HelpMessage = $Choices[$i].Replace('&', '')
    }
    $descriptions += $c
}

$Host.UI.PromptForChoice($Caption, $Message, [System.Management.Automation.Host.ChoiceDescription[]]$descriptions, $DefaultChoice)

Now we test it:

Get-Choice2 'Title' 'Message' -DefaultChoice 0, 1, 2 -Choices @(
    'Choice &1', 'This is choice 1'
    'Choice &2', ''
    'Choice &3', ''
    'Choice &4', ''
    'Choice &5', ''
    'Choice &6', ''
    'Choice &7', ''
    'Choice &8', ''
    'Choice &9', ''
    'Choice &0', ''
)

It prints 10 choices, the first 3 are highlighted (in the console host), and prompts:

0> Test-Get-Choice2.ps1
Title
Message
[1] Choice 1
[2] Choice 2
[3] Choice 3
[4] Choice 4
[5] Choice 5
[6] Choice 6
[7] Choice 7
[8] Choice 8
[9] Choice 9
[0] Choice 0
[?] Help
(default choices are 1,2,3)
Choice[0]:

If we press Enter immediately the output is the default 3 indexes: 0, 1, 2. If we type, for example: 5 + Enter + 3 + Enter + 1 + Enter + Enter then the output is 4, 2, 0.

It works. PowerShell ISE also supports this but the UI might be something better in GUI version, perhaps.

Roman Kuzmin
I wish I could give you more than one upvote. This is exactly what I was looking for. I really appreciate the extra attention you gave.
Mike Shepard