This is driving me nuts. If one runs the below script, cancels the $host.ui.promptforchoice
, and checks $Choice
, they get:
PS C:\> $Choice.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
PS C:\> write-host """$Choice"""
"-1"
PS C:\> $Choice -eq -1
True
What on earth am I missing in my do...while loop that has the script exiting (it isn't the return; I commented out the switch statement) without looping!
$s = ""
do
{
$Choice = $host.ui.promptforchoice($ScriptFileName, "$($s)User this script is running under is not an admin acount.`r`n`r`nRunning this script will cause multiple password entries throughout.`r`n`r`nRecommend logging out and logging back in as an admin, then re-running. Proceed anyway?", @("&Yes", "&No"), 1)
switch($Choice)
{
0 {write-host "hello";<#Log ...Proceeding with script#>}
1 {write-host "`r`n`r`nQuitting script. Please login under an admin account and rerun`r`n" -foregroundcolor red -backgroundcolor yellow; return}
}
$s = "Selection Cancelled. Please make a selection. No to quit the script`r`n`r`n"
}
while($Choice -eq -1)
If you want to be able to catch CTRL+C as an option you can set TreatControlCAsInput
to true
however, using $HOST.UI.PromptForChoice
is no longer an option if going this route. You can use ReadKey
in this case, here a simple example of how your code should look:
[console]::TreatControlCAsInput = $true
while ($true) {
Write-Host 'Options: [Y / N]'
switch ([System.Console]::ReadKey($true)) {
{ $_.KeyChar -eq 'Y' } { Write-Host 'Y, do stuff...' }
{ $_.KeyChar -eq 'N' } { Write-Host 'Quitting script...'; return }
{ $_.Modifiers -eq 4 -and $_.Key -eq 67 } { Write-Host 'Ctrl+C... do something' }
default { Write-Host 'Invalid choice' }
}
}
Another option that wouldn't allow the user to CTRL+C during the prompt, would be to use a MessageBox
from Windows Forms. You can also combine this approach with TreatControlCAsInput
set to true
if you also want them to avoid being able to terminate the script on one of the switch options code paths.
Add-Type -AssemblyName System.Windows.Forms
while ($true) {
$result = [System.Windows.Forms.MessageBox]::Show(
'Do stuff?',
'Doing stuff',
[System.Windows.Forms.MessageBoxButtons]::YesNo, # Probably just 'OK' is better here
[System.Windows.Forms.MessageBoxIcon]::Question)
switch ($result) {
([System.Windows.Forms.DialogResult]::Yes) { Write-Host 'Do stuff' }
([System.Windows.Forms.DialogResult]::No) { Write-Host 'Quitting...'; return }
}
}