How to get Do-While Loop to work in network based PowerShell script? - powershell

Thank you to all who help me figure out what is going on.
The code I am using searches for the response for hog breeds and validates the response isn't garbage. If it's garbage the do loop repeats or exits based on response.
#Get the location of this script
$ScriptPath = (Split-Path $Myinvocation.MyCommand.path -Parent)
$TemPath = "$ScriptPath\_Template"
$NewTemPath = "$ScriptPath\_New_TEMPLATE"
$EarNotchPath = "$ScriptPath\EarNocthes"
$BoarPath = "$ScriptPath\_Boar_Samples"
$SowPath = "$ScriptPath\_Sow_Samples"
$GiltPath = "$ScriptPath\_Gilt_Samples"
$BarrowPath = "$ScriptPath\_Barrow_Samples"
$LittersPath = "$ScriptPath\_Litters_Samples"
Do {
#Create variables and collect information from user of script.
$CUST= Read-Host 'Enter Customer Name '
$BoarPath= Read-Host 'Enter Selected Boar Name (example: WildHog)'
$SowPath= Read-Host 'Enter Selected Sow Name (example: TrueBlue)'
$HogBreeds= Read-Host 'Enter Hereford, Yorkshire, Hampshire, Duroc, China_Poland'
##Error Check $HogBreeds
If ('Hereford', 'Yorkshire', 'Hampshire', 'Duroc', 'China_Poland' -cnotcontains $HogBreeds){
If ('Hereford', 'Yorkshire', 'Hampshire', 'Duroc', 'China_Poland' -contains $HogBreeds){
$TextInfo = (Get-Culture).TextInfo
Switch ($HogBreeds) {
{$_ -in 'Hereford','Yorkshire','Duroc'} { $HogBreeds = $HogBreeds.ToUpper() }
'CHINA_Poland' { $HogBreeds = $HogBreeds.Substring(0,7).ToUpper() + $HogBreeds.Substring(7,5).ToLower() }
}
$Restart = 'StopDoLoop'
} Else {
Write-Warning 'You didnt enter one of: Hereford, Yorkshire, Hampshire, Duroc, China_Poland or Your response was not recongized.'
$ANSWER = Read-Host 'Do you want to start over (Yes/No) - type Yes or No'
If ($ANSWER -eq 'Yes') { $Restart = 'StopDoLoop'}
If ($ANSWER -eq 'No') { Exit }
}
}
} Until ($Restart -eq 'StopDoLoop')
If I run this code with Windows PowerShell ISE Administrator the 'Do-While' loop executes with no problems. However, if I just right click on Do-While.ps1 script opening in PowerShell non-ISE the 'Do-While' loop repeats and never breaks. What gives?
Do you see any way to improve the code? I am also wondering about adding a string length check to the $Answer variable, and I fully admit I have not researched this other than a conversation I had with a friend.

I figured out the issue and now I have my code working and wanted to give you all the solution to the problem.
#Run as Adminstrator
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
#Get the location of this script
$ScriptPath = (Split-Path $Myinvocation.MyCommand.path -Parent)
$TemPath = "$ScriptPath\_Template"
$NewTemPath = "$ScriptPath\_New_TEMPLATE"
$EarNotchPath = "$ScriptPath\EarNocthes"
$BoarPath = "$ScriptPath\_Boar_Samples"
$SowPath = "$ScriptPath\_Sow_Samples"
$GiltPath = "$ScriptPath\_Gilt_Samples"
$BarrowPath = "$ScriptPath\_Barrow_Samples"
$LittersPath = "$ScriptPath\_Litters_Samples"
Do {
#Create variables and collect information from user of script.
$CUST= Read-Host 'Enter Customer Name '
$BoarPath= Read-Host 'Enter Selected Boar Name (example: WildHog)'
$SowPath= Read-Host 'Enter Selected Sow Name (example: TrueBlue)'
$HogBreeds= Read-Host 'Enter Hereford, Yorkshire, Hampshire, Duroc, China_Poland'
##Error Check $HogBreeds
If ('Hereford', 'Yorkshire', 'Hampshire', 'Duroc', 'China_Poland' -cnotcontains $HogBreeds){
If ('Hereford', 'Yorkshire', 'Hampshire', 'Duroc', 'China_Poland' -contains $HogBreeds){
$TextInfo = (Get-Culture).TextInfo
Switch ($HogBreeds) {
{$_ -in 'Hereford','Yorkshire','Duroc'} { $HogBreeds = $HogBreeds.ToUpper() }
'CHINA_Poland' { $HogBreeds = $HogBreeds.Substring(0,7).ToUpper() + $HogBreeds.Substring(7,5).ToLower() }
}
$Restart = 'StopDoLoop'
} Else {
Write-Warning 'You didnt enter one of: Hereford, Yorkshire, Hampshire, Duroc, China_Poland or Your response was not recongized.'
$ANSWER = Read-Host 'Do you want to start over (Yes/No) - type Yes or No'
If ($ANSWER -eq 'Yes') { $Restart = 'StopDoLoop'}
If ($ANSWER -eq 'No') { Exit }
}
}
} Until ($Restart -eq 'StopDoLoop')
}
Wrapping my not just my 'Do-While-Loop' but all my code in the first 'IF' statement has resolved the problem where I can now run all my code in an administrator PowerShell window without requiring PowerShell ISE.
I do hope this helps everyone who comes across this posting.
Thank you all for your help.

Related

Computer Type and Asset tag merge using PS

I wrote out a PowerShell Script to rename my computer, add it to specific OU's and join it to the domain. My question is we have two types of computer Desktop (DT) and Laptop (LT) and we give it an asset tag and I would like for it to ask me to select if it is a desktop or laptop and then ask for the asset tag number and then add the DT or LT in front of the asset tag number as the computer name (sorry if confused) example: DT01234 or LT01235. I will post my code below and bold the area that renames the computer. Any and all help would be greatly appreciated.
Write-Host "Select Desktop or Laptop [1-2] [Default 1]:
1. Desktop
2. Laptop"
$computertype = Read-Host
Write-Host "Please Enter Asset Tag"
$NewCompName = Read-Host
$renamecomputer = $true
if ($NewCompName -eq "" -or $NewCompName -eq $env:COMPUTERNAME) {$NewCompName = $env:COMPUTERNAME; $renamecomputer = $false}
Write-Host "Please enter your desired location [1-7] [Default 1]:
1. Test
2. Compliance Stations
3. Controls Stations
4. Processing Stations
5. QC Stations
6. Receiving Stations
7. Shipping Stations"
$ou = Read-Host
#$creds = Get-Credential
function Test-ADCrential{
[CmdletBinding()]
param(
[pscredential]$Credential
)
try {
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
if(!$Credential) {
$Credential = Get-Credential -EA Stop
}
if($Credential.username.split("\").count -ne 2) {
throw "You haven't entered credentials in DOMAIN\USERNAME format. Given value : $($Credential.Username)"
}
$DomainName = $Credential.username.Split("\")[0]
$UserName = $Credential.username.Split("\")[1]
$Password = $Credential.GetNetworkCredential().Password
$PC = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, $DomainName)
if($PC.ValidateCredentials($UserName,$Password)) {
Write-Verbose "Credential validation successful for $($Credential.Username)"
return $True
} else {
throw "Credential validation failed for $($Credential.Username)"
}
} catch {
Write-Verbose "Error occurred while performing credential validation. $_"
return $False
}
}
$mycreds = Get-Credential
Write-Host "Adding $NewCompName to the domain"
Read-Host "Press enter to change computer name"
if ($renamecomputer -eq $true)
{Rename-Computer -NewName $NewCompName -DomainCredential $mycreds}
Read-Host "Press enter to restart computer"
Restart-Computer
Looks like you want something like this
if ($NewCompName -eq "" -or $NewCompName -eq $env:COMPUTERNAME)
{
$NewCompName = $env:COMPUTERNAME; $renamecomputer = $false
}
elseif($NewCompName -inotmatch "^DT|^LT")
{
switch($computertype )
{
1{$NewCompNamePrefix = "DT"}
2{$NewCompNamePrefix = "LT"}
default{}
}
$NewCompName = $NewCompNamePrefix + $NewCompName
}
the -inotmatch is just making sure that if a $newcompname is inputted that already looks like DTwhatever or LTwhatever, it won't append an extra LT or DT
Unrelated (just me being a bit nitpicky):
Look into Read-host -Prompt and nest the prompts into do while loops, so you can validate that the input is what you're expecting.
something like this
$properChoices = #("a","b","c")
do
{
$choice = (Read-Host -Prompt "pick a, b, or c").ToLower()
switch($choice)
{
"a"{"You picked $choice"}
"b"{"You picked $choice"}
"c"{"You picked $choice"}
default{Write-Warning "Invalid Input"}
}
}
while($choice -notin $properChoices)

What is stopping this powershell script from running

A friend of mine asked me to make a script however I have not worked with power shell. I can't seem to find anything that tells me why this script doesn't run. Any tips are appreciated.
The script is meant to run through all files in a folder and the user enters in information given in the document name. This then is put in the meta data of the file and it moves on to the next file.
#1. opens file or first 10 lines (if plain text)
#1.5 get old name and add it to the new name
#2.gets input from the user as follows
#b)date
#c)classification
#d)fileNum
#e)Org
#f)Lang
#3.fills metadata with some input as params
#4.sets name to YYYYMMDD-classification-fileNum-ORG-NAME-Lang
#5.print out current file name for user to change if needed and confirm
foreach($list in $web.Lists) {
#main folder, change as needed
if ($list.Title -ne "My Documents") {
continue
}
Write-Host $list.Title
foreach($folder in $list.RootFolder.SubFolders) {
#this is where we get the sub folder, change as needed
if ($folder.Name -ne "Documents to be changed") {
continue
}
Invoke-Item $file
$dateVal = Get-Date -Format "MM/dd/yyyy"
$Name = $file.BaseName
$Class = Read-Host -Prompt 'Input classification'
$fileNum = Read-Host -Prompt 'Input file number'
$Org = Read-Host -Prompt 'Input Orginization'
$Lang = Read-Host -Prompt 'Input Language e for English and f for french'
if($Lang -eq "E"){
$Lang = "EN"
} else if($Lang -eq "e"){
$Lang = "EN"
}else if($Lang -eq "F"){
$Lang = "FR"
}else{
$Lang = "FR"
}
$file.CheckOut();
$file.Properties['Classifictation'] = $Class
$file.Properties['FileNumber'] = $fileNum
$file.Properties['Orginization'] = $Org
$file.Properties['Language'] = $Lang
$file.Properties['Old Name'] = $Name
$file.Update();
$file.CheckIn('Updated file');
Write-Host "Current name is: '$dateVal'-'$Class'-'$dateVal'-'$fileNum'-'$Org'-'$Name'-'$Lang' "
$Correct = Read-Host -Prompt 'enter y if correct, n if incorrect'
if($Correct -eq "y"){
Rename-Item $file -NewName "'$dateVal'-'$Class'-'$dateVal'-'$fileNum'-'$Org'-'$Name'-'$Lang' "
}else{
$Corrected = Read-Host -Prompt 'Please enter the corrected name'
Rename-Item $file -NewName "'$Corrected'"
}
Get-SmbOpenFile | Where { $_.path -match $file}| Close-SmbOpenFile -Force
}
}

Using Read-host with Input validation and TRAP

I'm just a typical admin trying to make a simple script for some IT assistants in remote offices, to make domain joins easier while minimizing potential errors. The script's end game is to run the one-liner command Add-Computer -DomainName $DomainToJoin -OUPath $LocDN -NewName $WS_NewName -Restart.
But the whole script is supposed to include input validation for the computer's new name as well as for the target OU for the two-letter code for the remote office.
Googling for code snippets for days, esp. from sites like yours, was very helpful. But the problem I have now is I couldn't find the right codes to combine Read-Host , input length validation, and TRAP to work together without losing the value for my variables.
Pardon my coding as obviously I'm no real PS scripter, and I know the wrong portions of it are very basic. I would want to spend more time if I had the luxury, but I would really so much appreciate it if you could point me in the right direction.
Thank you so much in advance.
Please see my code below:
# START: Display name and purpose of invoked script
$path = $MyInvocation.MyCommand.Definition
Clear-Host
Write-Host $path
Write-Host " "
Write-Host "This script will allow you to do the following in a single-step process:"
Write-Host "(1) RENAME this computer"
Write-Host "(2) JOIN it to MYDOMAIN"
Write-Host "(3) MOVE it to a target OU"
Write-Host "(4) REBOOT"
Write-Host " "
Pause
# Function: PAUSE
Function Pause ($Message = "Press any key to continue . . . ") {
if ((Test-Path variable:psISE) -and $psISE) {
$Shell = New-Object -ComObject "WScript.Shell"
$Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)
}
else {
Write-Host -NoNewline $Message
[void][System.Console]::ReadKey($true)
Write-Host
}
Write-Host " "
}
# Function: Define the parameters
Function Define-Parameters {
# Specify new computer name, with validation and TRAP
$WS_NewName = $null
while ($null -eq $WS_NewName) {
[ValidateLength(8,15)]$WS_NewName = [string](Read-Host -Prompt "NEW NAME of computer (8-15 chars.)" )
TRAP {"" ;continue}
}
Write-Host " "
# Domain to join.
$DomainToJoin = 'mydomain.net'
# Specify the target OU, with validation and trap
$baseOU='OU=Offices OU,DC=mydomain,DC=net'
$OU2 = $null
while ($null -eq $OU2) {
[ValidateLength(2,2)]$OU2 = [string](Read-Host -Prompt 'Target OU (TWO-LETTER code for your office)' )
TRAP {"" ;continue}
}
Write-Host " "
$LocDN = "OU=$OU2,$baseOU"
}
# Function: Summary and confirmation screen for defined parameters.
Function Confirm-Parameters {
Write-Host "==========================================================================="
Write-Host "Please confirm that you are joining this computer to
$DomainToJoin (MYDOMAIN)"
Write-Host "with the following parameters:"
Write-Host ""
Write-Host ""
Write-Host "Computer's NEW NAME: $WS_NewName"
# Write-Host "Domain to Join: $DomainToJoin"
Write-Host "TARGET mission OU: $OU2"
}
# Call Define-Parameters Function
Define-Parameters
# Call Confirm-Parameters Function
Confirm-Parameters
<#
Some more code here
#>
# FINAL COMMAND if all else works: Join the computer to the domain, rename it, and restart it.
# Add-Computer -DomainName $DomainToJoin -OUPath $LocDN -NewName $WS_NewName -Restart
In your code, you have a lot of things defined very strangely. Your functions create a new scope and the variables you're trying to define therein will disappear after calling them unless you change the variable scope (in this case, to $script: or $global:). Also, to use functions, you need to define them first (your Pause doesn't actually do anything)
Here's something you can do with your Define-Parameters function (I suggest looking at Get-Verb)
# Domain to join.
$DomainToJoin = 'mydomain.net'
# Function: Define the parameters
Function Get-Parameters {
do {
$global:WS_NewName = Read-Host -Prompt 'NEW NAME of computer (8-15 chars)'
} until ($WS_NewName.Length -gt 7 -and $WS_NewName.Length -lt 16)
''
do {
$global:OU2 = Read-Host -Prompt 'Target OU (TWO-LETTER code for your office)'
} until ($OU2 -match '^[a-z]{2}$')
''
$OU2 = "OU=$global:OU2,OU=Offices OU,DC=mydomain,DC=net"
}
I'd strongly recommend moving away from the ISE to do your testing and test in an actual powershell console.
Perhaps Try/Catch block instead of trap?
Try {
[ValidatePattern('^\w{8,15}$')]$compname=read-host 'enter comp name' -ErrorAction Stop
[ValidatePattern('^\w{2}$')]$OU=read-host 'enter OU name' -ErrorAction Stop
}
Catch {
$ErrorMessage = $_.Exception.Message
$ErrorLineNumber = $_.InvocationInfo.ScriptLineNumber
$ErrorCommandName = $_.InvocationInfo.InvocationName
Write-Error -Message "The error message was: <$ErrorMessage>, script line: <$ErrorLineNumber>, command name: <$ErrorCommandName>"
exit 255
}

do until user input yes/no

I am trying to write a simple do..until loop and it does not work:
$yesNo = Read-Host -Prompt 'Do you want to add alternative DNS names or IPs into Certificate? Y/N: '
do {
$dnsipname = Read-Host -Prompt "Please input DNS or IP as dns=alternativeCNname or ip=ipName: "
Write-Output "$dnsipname"
$strQuit = Read-Host " do you want to add another DNS? (Y/N)"
do {
$dnsipname = Read-Host -Prompt "Please input DNS or IP as dns=alternativeCNname or ip=ipName: "
Write-Output "$dnsipname"
Add-Content D:\Scripts\expiringCerts\request.inf '`r`n_continue_ = "$dnsipname"'
} until ($strQuit -eq "Y" -or "y")
} until ($yesNo -eq "Y" -or "y")
This one does loop twice only, but it should loop every time I hit Y but when I hit N or n It should break.
Any ideas?
In PowerShell you have basically three options to prompt a user for a yes/no choice.
The Read-Host cmdlet:
$msg = 'Do you want to add alternative DNS names or IPs into Certificate? [Y/N]'
do {
$response = Read-Host -Prompt $msg
if ($response -eq 'y') {
# prompt for name/address and add to certificate
}
} until ($response -eq 'n')
Use -like 'y*' and -like 'n*' if you want to ignore trailing characters in the response.
The PromptForChoice() method:
$title = 'Certificate Alternative Names'
$msg = 'Do you want to add alternative DNS names or IPs?'
$options = '&Yes', '&No'
$default = 1 # 0=Yes, 1=No
do {
$response = $Host.UI.PromptForChoice($title, $msg, $options, $default)
if ($response -eq 0) {
# prompt for name/address and add to certificate
}
} until ($response -eq 1)
The choice command:
$msg = 'Do you want to add alternative DNS names or IPs into Certificate'
do {
choice /c yn /m $msg
$response = $LASTEXITCODE
if ($response -eq 0) {
# prompt for name/address and add to certificate
}
} until ($response -eq 1)
I think you don't need two do-until loop. I also would prefer a do-while (while he is confirming with y or Y).
Your string interpolation on the Add-Content doesn't work because you are using single quotes. I would leverage a format string here:
$yesNo = Read-Host -prompt 'Do you want to add alternative DNS names or IPs into Certificate? Y/N: '
if ($yesNo -eq 'y')
{
do
{
$dnsipname = read-host -prompt "Please input DNS or IP as dns=alternativeCNname or ip=ipName: "
Write-output "$dnsipname"
Add-Content -Path "D:\Scripts\expiringCerts\request.inf" -value ('`r`n_continue_ = "{0}"' -f $dnsipname)
$strQuit = Read-Host " do you want to add another DNS? (Y/N)"
}
while($strQuit -eq 'y')
}
You need to have the condition that you are evaluating in the until statement ($strQuit for your example) inside the do loop for it to be updated.
Wrapping the do loop in an if statement also makes the process friendlier to the user as it ask them before continuing to prompt.
$dnsipname = read-host -prompt "Please input DNS or IP as dns=alternativeCNname or ip=ipName: "
Write-Output $dnsipname
Add-Content D:\Scripts\expiringCerts\request.inf '`r`n_continue_ = "$dnsipname"'
if ((Read-Host "Do you want to add another DNS or IP? (Y/N)") -eq "Y") {
do {
$dnsipname = Read-Host "Please input DNS or IP as dns=alternativeCNname or ip=ipName: "
Write-output "$dnsipname"
Add-Content D:\Scripts\expiringCerts\request.inf '`r`n_continue_ = "$dnsipname"'
$strQuit = Read-Host "Do you want to add another DNS or IP? (Y/N)"
}
until ($strQuit -eq "N")
}

How to Use -confirm in PowerShell

I'm trying to take user input and before proceeding I would like get a message on screen and than a confirmation, whether user wants to proceed or not. I'm using the following code but its not working:
write-host "Are you Sure You Want To Proceed:" -Confirm
-Confirm is a switch in most PowerShell cmdlets that forces the cmdlet to ask for user confirmation. What you're actually looking for is the Read-Host cmdlet:
$confirmation = Read-Host "Are you Sure You Want To Proceed:"
if ($confirmation -eq 'y') {
# proceed
}
or the PromptForChoice() method of the host user interface:
$title = 'something'
$question = 'Are you sure you want to proceed?'
$choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))
$decision = $Host.UI.PromptForChoice($title, $question, $choices, 1)
if ($decision -eq 0) {
Write-Host 'confirmed'
} else {
Write-Host 'cancelled'
}
Edit:
As M-pixel pointed out in the comments the code could be simplified further, because the choices can be passed as a simple string array.
$title = 'something'
$question = 'Are you sure you want to proceed?'
$choices = '&Yes', '&No'
$decision = $Host.UI.PromptForChoice($title, $question, $choices, 1)
if ($decision -eq 0) {
Write-Host 'confirmed'
} else {
Write-Host 'cancelled'
}
This is a simple loop that keeps prompting unless the user selects 'y' or 'n'
$confirmation = Read-Host "Ready? [y/n]"
while($confirmation -ne "y")
{
if ($confirmation -eq 'n') {exit}
$confirmation = Read-Host "Ready? [y/n]"
}
Read-Host is one example of a cmdlet that -Confirm does not have an effect on.-Confirm is one of PowerShell's Common Parameters specifically a Risk-Mitigation Parameter which is used when a cmdlet is about to make a change to the system that is outside of the Windows PowerShell environment. Many but not all cmdlets support the -Confirm risk mitigation parameter.
As an alternative the following would be an example of using the Read-Host cmdlet and a regular expression test to get confirmation from a user:
$reply = Read-Host -Prompt "Continue?[y/n]"
if ( $reply -eq 'y' ) {
# Highway to the danger zone
}
The Remove-Variable cmdlet is one example that illustrates the usage of the -confirm switch.
Remove-Variable 'reply' -Confirm
Additional References: CommonParameters, Write-Host, Read-Host, Comparison Operators, Regular Expressions, Remove-Variable
Here is the documentation from Microsoft on how to request confirmations in a cmdlet. The examples are in C#, but you can do everything shown in PowerShell as well.
First add the CmdletBinding attribute to your function and set SupportsShouldProcess to true. Then you can reference the ShouldProcess and ShouldContinue methods of the $PSCmdlet variable.
Here is an example:
function Start-Work {
<#
.SYNOPSIS Does some work
.PARAMETER Force
Perform the operation without prompting for confirmation
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
# This switch allows the user to override the prompt for confirmation
[switch]$Force
)
begin { }
process {
if ($PSCmdlet.ShouldProcess('Target')) {
if (-not ($Force -or $PSCmdlet.ShouldContinue('Do you want to continue?', 'Caption'))) {
return # user replied no
}
# Do work
}
}
end { }
}
write-host does not have a -confirm parameter.
You can do it something like this instead:
$caption = "Please Confirm"
$message = "Are you Sure You Want To Proceed:"
[int]$defaultChoice = 0
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Do the job."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Do not do the job."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$choiceRTN = $host.ui.PromptForChoice($caption,$message, $options,$defaultChoice)
if ( $choiceRTN -ne 1 )
{
"Your Choice was Yes"
}
else
{
"Your Choice was NO"
}
For when you want a 1-liner
while( -not ( ($choice= (Read-Host "May I continue?")) -match "^(y|n)$")){ "Y or N ?"}
Write-Warning "This is only a test warning." -WarningAction Inquire
from:
https://serverfault.com/a/1015583/584478
Here's a solution I've used, similiar to Ansgar Wiechers' solution;
$title = "Lorem"
$message = "Ipsum"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "This means Yes"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "This means No"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $Options, 0)
Switch ($result)
{
0 { "You just said Yes" }
1 { "You just said No" }
}
A slightly prettier function based on Ansgar Wiechers's answer. Whether it's actually more useful is a matter of debate.
function Read-Choice(
[Parameter(Mandatory)][string]$Message,
[Parameter(Mandatory)][string[]]$Choices,
[Parameter(Mandatory)][string]$DefaultChoice,
[Parameter()][string]$Question='Are you sure you want to proceed?'
) {
$defaultIndex = $Choices.IndexOf($DefaultChoice)
if ($defaultIndex -lt 0) {
throw "$DefaultChoice not found in choices"
}
$choiceObj = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
foreach($c in $Choices) {
$choiceObj.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList $c))
}
$decision = $Host.UI.PromptForChoice($Message, $Question, $choiceObj, $defaultIndex)
return $Choices[$decision]
}
Example usage:
PS> $r = Read-Choice 'DANGER!!!!!!' '&apple','&blah','&car' '&blah'
DANGER!!!!!!
Are you sure you want to proceed?
[A] apple [B] blah [C] car [?] Help (default is "B"): c
PS> switch($r) { '&car' { Write-host 'caaaaars!!!!' } '&blah' { Write-Host "It's a blah day" } '&apple' { Write-Host "I'd like to eat some apples!" } }
caaaaars!!!!
This version asks if the user wants to perform an action before continuing with the rest of the script.
DO
{
$confirmation = Read-Host "Do want Action before continue? [Y/N]"
if ($confirmation -eq 'y') {
write-Host "Doing the Action"
}
} While (($confirmation -ne 'y') -and ($confirmation -ne 'n'))
I prefer a popup.
$shell = new-object -comobject "WScript.Shell"
$choice = $shell.popup("Insert question here",0,"Popup window title",4+32)
If $choice equals 6, the answer was Yes
If $choice equals 7, the answer was No