PowerShell Prompt for Yes/No Input (6 Ways)

To prompt for yes/no input in PowerShell, ask with Read-Host and check the answer with -in 'y', 'yes'. The -in operator ignores case, so Y, y and YES all count:

$reply = Read-Host -Prompt 'Restart the print spooler now? (y/n)'

if ($reply -in 'y', 'yes') { 'Restarting the spooler...' } else { 'Skipped. Nothing was restarted.' }

Output (I typed Y):

Restart the print spooler now? (y/n): Y
Restarting the spooler...

That’s enough for a quick script. Below are sturdier options: a loop that rejects bad answers, a reusable function with a default, PowerShell’s built-in choice menu, and -Confirm support.

I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, with the same results.

Keep asking until you get a yes or no

People type “sure”, press Enter by accident, or add spaces. A do/until loop asks again until the answer is valid, and .Trim() drops the extra spaces:

do {
    $reply = (Read-Host -Prompt 'Archive the 2025 invoices? (y/n)').Trim()
    $valid = $reply -in 'y', 'yes', 'n', 'no'
    if (-not $valid) { 'Please answer y or n.' }
} until ($valid)

if ($reply -like 'y*') { 'Archiving 318 invoices...' } else { 'Cancelled.' }

Output (I typed sure, then nothing, then ” no “):

Archive the 2025 invoices? (y/n): sure
Please answer y or n.
Archive the 2025 invoices? (y/n):
Please answer y or n.
Archive the 2025 invoices? (y/n):  no
Cancelled.

-like 'y*' works for the final check because the loop has already limited the answer to y, yes, n or no. PowerShell while and do loops covers the loop types in more detail.

A reusable Confirm-Action function with a default

Most command-line tools show the default in capitals, like [y/N], and use it when you just press Enter. This function does the same and returns $true or $false:

function Confirm-Action {
    param(
        [Parameter(Mandatory)] [string]$Question,
        [switch]$DefaultYes
    )
    $hint = if ($DefaultYes) { '[Y/n]' } else { '[y/N]' }
    while ($true) {
        $reply = (Read-Host -Prompt "$Question $hint").Trim()
        if ($reply -eq '')         { return [bool]$DefaultYes }
        if ($reply -in 'y', 'yes') { return $true }
        if ($reply -in 'n', 'no')  { return $false }
    }
}

if (Confirm-Action -Question 'Delete 12 temp files') { 'Deleting...' } else { 'Kept the files.' }
if (Confirm-Action -Question 'Email the summary to IT' -DefaultYes) { 'Sending...' } else { 'Not sent.' }

Output (I pressed Enter at both prompts):

Delete 12 temp files [y/N]:
Kept the files.
Email the summary to IT [Y/n]:
Sending...
PowerShell Confirm-Action function with a y/N default answer
Enter picks the capitalized default (Windows PowerShell 5.1)

Default to No for anything destructive, like deleting files. Save Yes as the default for safe steps, like sending a report.

Use PowerShell’s built-in choice prompt

$Host.UI.PromptForChoice() shows the same [Y] Yes [N] No menu that PowerShell’s own cmdlets use. It returns the index of the choice, so 0 is Yes here:

$yes = [System.Management.Automation.Host.ChoiceDescription]::new('&Yes', 'Disable the account now')
$no  = [System.Management.Automation.Host.ChoiceDescription]::new('&No', 'Leave the account as it is')

$answer = $Host.UI.PromptForChoice('Disable account', 'Disable the account for jsmith?', @($yes, $no), 1)
if ($answer -eq 0) { 'Account disabled.' } else { 'No change made.' }

Output (I typed ? for help, then y):

Disable account
Disable the account for jsmith?
[Y] Yes  [N] No  [?] Help (default is "N"): ?
Y - Disable the account now
N - Leave the account as it is
[Y] Yes  [N] No  [?] Help (default is "N"): y
Account disabled.
PowerShell PromptForChoice yes/no prompt with help text
The ampersand sets each hotkey, and ? shows the help text (PowerShell 7)

The last argument is the default index, so 1 makes No the default. The PromptForChoice reference covers the other overloads.

Add -Confirm and -WhatIf to your own function

If your script changes something, the most PowerShell-like way to ask is ShouldProcess. You get -Confirm and -WhatIf for free, and callers can skip the prompt in automation:

function Remove-OldReport {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param([Parameter(Mandatory)] [string]$Name)

    if ($PSCmdlet.ShouldProcess($Name, 'Delete report')) {
        "Deleted $Name"
    }
}

Remove-OldReport -Name 'q1-sales.csv'
Remove-OldReport -Name 'q2-sales.csv' -Confirm:$false

Output (I typed n):

Confirm
Are you sure you want to perform this action?
Performing the operation "Delete report" on target "q1-sales.csv".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): n
Deleted q2-sales.csv
PowerShell ShouldProcess confirm prompt with Yes, Yes to All and No
The first call asks, the second skips the prompt with -Confirm:$false (PowerShell 7)

Watch out: this prompt defaults to Yes, so pressing Enter deletes the file. ConfirmImpact = ‘High’ is what makes it ask without -Confirm.

Preview changes with -WhatIf

The same function also supports -WhatIf, which only describes what would happen:

function Remove-OldReport {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param([Parameter(Mandatory)] [string]$Name)

    if ($PSCmdlet.ShouldProcess($Name, 'Delete report')) {
        "Deleted $Name"
    }
}

Remove-OldReport -Name 'q3-sales.csv' -WhatIf

Output:

What if: Performing the operation "Delete report" on target "q3-sales.csv".

Microsoft’s guide to ShouldProcess explains ConfirmImpact and $ConfirmPreference in more depth.

Use choice.exe for a single keypress with a timeout

Windows’ choice command takes one keypress without Enter and can pick a default after a timeout. It sets $LASTEXITCODE to the position of the key pressed:

choice /C YN /D N /T 3 /M 'Install the update'
if ($LASTEXITCODE -eq 1) { 'Installing...' } else { 'Update skipped.' }

Output (no key pressed for 3 seconds):

Install the update [Y,N]?N
Update skipped.

/D sets the default and /T the seconds to wait, which keeps an unattended script from hanging forever. The choice command reference lists every switch.

Show a Yes/No message box

For users who don’t live in the console, a Windows Forms message box is friendlier. It returns Yes or No as a DialogResult:

Add-Type -AssemblyName System.Windows.Forms
$result = [System.Windows.Forms.MessageBox]::Show('Install the printer driver?', 'Setup', 'YesNo', 'Question')
if ($result -eq 'Yes') { 'Installing...' } else { 'Skipped.' }

The Add-Type line matters. Without it, the MessageBox type isn’t loaded in a plain console, which is why copied snippets often fail.

Don’t prompt in scheduled tasks

Read-Host, PromptForChoice and ShouldProcess prompts all fail under -NonInteractive, as in many scheduled tasks and CI pipelines. The error says “Read and Prompt functionality is not available.”

Give your script a -Force switch that skips the question, and call ShouldProcess functions with -Confirm:$false.

Microsoft notes this in the Read-Host documentation. For other kinds of input, like numbers and passwords, see prompting for input in PowerShell.

Frequently Asked Questions

How do I prompt for yes or no in PowerShell?

Use Read-Host and check the answer: $r = Read-Host 'Continue? (y/n)'; if ($r -in 'y', 'yes') { ... }. The -in operator ignores case.

How do I make Enter pick a default answer?

Check for an empty reply first: if ($reply -eq '') { $reply = 'n' }. Show the default in capitals, like [y/N], so users know.

What does PromptForChoice return?

The index of the chosen option. With ‘&Yes’ and ‘&No’ in that order, Yes returns 0 and No returns 1.

How do I add a confirmation prompt to my function?

Add [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] and wrap the change in if ($PSCmdlet.ShouldProcess($target)) { }. You also get -WhatIf.

How do I skip a confirmation prompt in PowerShell?

Pass -Confirm:$false to cmdlets and functions that support ShouldProcess. Some cmdlets also have a -Force switch.

Keep building interactive scripts with these: