Ways to clean up my yes/no prompts in powershell

So, for work they gave me this "automation" script they wanted to employ. But I've literally never written anything in Powershell so naturally I re-wrote the whole thing from scratch cause it was booty (not that mine is much better) but after 5 days of Powershell experience I think I've made decent progress. However, my yes/no prompts get quite messy and I hope the people who actually know what they're doing here have some tips for me. So here's my code.

These are the prompt declarations...

 $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&yes" $no = New-Object System.Management.Automation.Host.ChoiceDescription "&no" $help = New-Object System.Management.Automation.Host.ChoiceDescription "&help" $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no, $help)
These are part of the checks for the Datacenter portion. (The whole script block is Datacenters, Clusters, Hosts utilizing VMware PowerCLI.) While ($ChoiceTask -eq "Check Datacenters"){ Clear-Host Write-Output "Would you like to create any Datacenters?" $result = $host.ui.PromptForChoice($title, $message, $options, 0) switch($result){ 0{$ChoiceTask = "Datacenters" $MadeDatacenters = $true} 1{$ChoiceTask = "Check Clusters" $MadeDatacenters = $false} 2{ Write-Output "A virtual datacenter is a container for all the inventory objects required to complete a fully functional environment for operating virtual machines. Recommended procedure is creating three datacenters. The UCS Datacenter, the vSAN Datacenter, and the Witness Datacenter. However, you may change this to fit your needs." Read-Host -Prompt "(Press 'Enter' to continue)" } } } #Creates appropriate amount of Datacenters for User While ($ChoiceTask -eq "Datacenters"){ Clear-Host $DataCenterAmount = ([String] $DataCenterAmount = (Read-Host "How many datacenters would you like to create?")) Clear-Host Write-Color -Text "You want to create ","$DataCenterAmount ","Datacenters. Is this correct?" -Color White,Yellow,White $result = $host.ui.PromptForChoice($title, $message, $options, 1) switch ($result){ 0{ Clear-Host [System.Collections.ArrayList]$DatacenterArray = @() $Curr = 1 While ($Curr -le $DataCenterAmount){ #Processes amount of datacenters to be created. Write-Color -Text "Please enter the name of Datacenter ","$Curr",":" -Color White,Yellow,White $DatacenterName = Read-Host Clear-Host Write-Color -Text "The name of Datacenter"," $Curr"," is"," $DatacenterName",". Is this correct?" -Color White,Yellow,White,Yellow,White $result = $host.ui.PromptForChoice($title, $message, $options, 1) switch ($result){ 0{ #After confirmation of Datacenter name - creates datacenter $folder = Get-Folder -NoRecursion try { New-Datacenter -Name $DatacenterName -Location $folder } catch{ Clear-Host Write-Color -text "[WARNING] An error has occured during the Datacenter creation process, a connection error may have ocurred." -color red Read-Host "(Press 'Enter' to continue:)" $ChoiceTask = "Standard Check" } $DatacenterArray.Add($DatacenterName) Clear-Host Write-Color -Text "Datacenter"," $DatacenterName"," successfully created! (Press 'Enter' to continue)" -Color White,Yellow,White Read-Host $Curr++ Clear-Host } 1{} } } $ChoiceTask = "Check Clusters" }#End 'Yes' Selection 1{} } }

As you can see, it gets really messy. But it's important the user makes sure that their choices are correct. From what I can tell this is the best way to yes/no prompt; but I'd like to really clean this up for my sake. If you missed the above, this is in conjunction with VMware's PowerCLI so if you don't recognize some actions that's why. And write-color is a custom function in order to simplify coloring of variables printed on screen. Even though I'm sure there's a much easier way to do that as well.

5

2 Answers

Use Splatting to pass long/large parameter sets to increase readablity:

$splat = @{ 'Text' = ('The name of Datacenter ', $Curr, ' is ', $DatacenterName, '. Is this correct?') 'Color' = (White,Yellow,White,Yellow,White)
}
Write-Color -Text $Text -Color $Color

Consider a wrapper Function:

Function Ask-ColoredQuestion ($Text, $Color) { Write-Color -Text $Text -Color $Color $host.ui.PromptForChoice($title, $message, $options, 0)
}
$splat = @{ 'Text' = ('The name of Datacenter ', $Curr, ' is ', $DatacenterName, '. Is this correct?') 'Color' = (White,Yellow,White,Yellow,White)
}
$Result = Ask-ColoredQuestion @splat

Even better, text color can be controlled via escape codes that can be part of your string. This will allow you to use the in-built -Prompt parameter of Read-Host or $message in PromptForChoice()

$esc = "$([char]27)"
$Red = "$esc[31m"
$Green = "$esc[32m"
$message = '{0}{1} {2}{3}' -f $Red, 'Hello', $Green, 'World'
$message

enter image description here

So you might want to re-tool Write-Color to compose a string with color escape codes and then pass that string to the buit-in prompts.

I think that's enough to get you started! :D

5

I found that I was doing a lot of prompts for yes/no answers, so I wrote a function to make it easier. This may provide you a few tips, but you may want to improve on my effort.

<#
.SYNOPSIS Prompts user for answer to a yes no prompt.
.DESCRIPTION The user is prompted with the argument, and asked for a reply. If the reply matches YES or NO (case insensitive) the value is true or false. Otherwise, the user is prompted again.
#>
function ask-user { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [string] $question ) Process { $answer = read-Host $question if ("YES","YE","Y" -contains $answer) {$true} elseif ("NO", "N" -contains $answer) {$false} else {ask-user $question} }
} # End function ask-user
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like