A nicer PromptForChoice for the PowerShell Console Host

378322049_c01db2cbf5_m
Sometimes it’s not possible to fully automate a certain process and we need some input from the user(s) of the script in order to determine the further path of action. If this is based on a fixed set of choices the built-in PromptForChoice method can come to the rescue. Here is an example:

Running the code below in PowerShell ISE will produce the following result:

PromptForChoiceISE
Running the same from the PowerShell console though will not look as fancy:
PromptForChoiceConsole
The reason for the difference is that the underlying PromptForChoice method on the System.Management.Automation.Host.PSHostUserInterface is declared as an abstract method. This basically means that the implementation details are up to the respective PowerShell host (as long as the method complies with the declaration).
As a result your script will not provide a consistent user experience across PowerShell hosts (e.g. ISE, Console). Because of this I wrote a little Windows.Form based helper function that provides the same features as PromptForChoice but will look the same across all PowerShell hosts:

Using Get-Choice like this:

Get-Choice "Pick Something!" (echo Option1 Option2 Option3) 2

Will look in both ISE and Console like that:

GetChoice
The most notable parts of the function are probably in the loop on lines 46-59. Where the buttons are created dynamically based on the options provided.:

foreach ($option in $Options){
        Set-Variable "button$index" -Value (New-Object System.Windows.Forms.Button)
        $temp = Get-Variable "button$index" -ValueOnly
        $temp.Size = New-Object System.Drawing.Size($buttonWidth,$buttonHeight)
        $temp.UseVisualStyleBackColor = $True
        $temp.Text = $option
        $buttonX = ($index + 1) * $spacing + $index * $buttonWidth
        $temp.Add_Click({ 
            $script:result = $this.Text; $form.Close() 
        })
        $temp.Location = New-Object System.Drawing.Point($buttonX,$buttonY)
        $form.Controls.Add($temp)
        $index++
}

Similar to the way it works in PromptForChoice preceding a character from within the option values with an ampersand (e.g. Option &1) will make the button accessible via ALT-key + the letter (e.g. ALT + 1).
The function can also be found in my GitHub repo.

shareThoughts


Photo Credit: zachstern via Compfight cc

Advertisements

I'd love to hear what you think

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s