For an assignment I have to prove that if statements can be placed within if statements in a Powershell script. Therefore I made the enclosed script. I am however not sure whether the script I have describes two separate if statements or would be considered an if within an if.
[int]$a = Read-host "Please input a number."
if ($a –eq 5) {
Write-Host “a is 5” }
if ($a –ne 5) {
Write-Host “a isn't 5” }
Read-host
Any help on this one?
Thank you for your answer. Why does this not work however?
if ($a –lt 2) {
if ($a –lt 3) {
if ($a –lt 4) {
if ($a –lt 5) {
Write-Host “a is less than 5” }
Write-Host “a is less than 4” }
Write-Host “a is less than 3” }
Write-Host “a is less than 2” }
Nah, these are two separate if statements. Nested would be:
if ($a –lt 5) {
if ($a –ne 2) {
Write-Host “a isn't 2” }
Write-Host “a is lt 5” }
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last year.
Improve this question
I'm working on writing a script in PowerShell for a Color guessing game. The computer randomly picks a color then the player tries to guess the color. I had it working up until I switched some lines of code in the script in an attempt to get these two variables to display correctly. Now, I can't get the code to run past the point where a player declares if they want to play the game or not. My current error is with a do loop, where the console doesn't see that I have a while loop, and so throws an error and won't run the rest of the code.
I managed to get the formatting fixed with Visual Studio Code's format document feature, but I still can't get this one while loop problem figured out.
Write-Host ''; 'Hello again my friend!'; ''
$name = Read-Host "What is your name?"
Write-Host ''; "It's good to see you again, $name! Would you like to guess my favorite color?"; ''
$command = Read-Host #'
"How do you answer? (Yes or No?)"
1. Yes (y)
2. No (n)
3. Quit (q)
Enter Choice
'#
switch -Wildcard ($command) {
'Y' { 'Yes!'; '' }
{ $_ -eq 'y' -or $_ -like 'Ye*' } {
Write-Host "This will be fun! Let us begin!"
Break
}
'N' { 'No!'; '' }
{ $_ -eq 'n' -or $_ -like 'No*' } {
Write-Host "That's too bad, perhaps another day!"
Exit
}
'Q' { 'Quit'; '' }
{ $_ -eq 'q' -or $_ -like 'qu*' } {
Write-Host 'So long!'
Exit
}
default {
'Invalid Command, Please start over.'
Exit
}
}
[string]$playagain = 'y'
[int]$playerwins = 0
[int]$compwins = 0
[int]$totalguesses = 0
[int]$playergames = 0
[int]$compgames = 0
[int]$round = 1
[int]$game = 1
$cpuchoice = $color
while ($playagain -eq 'y') {
Write-Host ''; "Game $game!"; ''
$cpuchoice = #([System.Enum]::GetValues([System.ConsoleColor])) | Get-Random -Count 1
do {
Write-Host "Round $round! What is my favorite color?"; ''
$listcolor = Read-Host "Would you like to see a list of available colors? Choose 'y' for yes, and 'n' for no."
if ($listcolor -eq 'y') {
[System.Enum]::GetValues([System.ConsoleColor])
}
elseif ($listcolor -eq 'n') {
Write-Host "Suit yourself, let's start."
}
else {
Write-Host "Your choice was invalid. Please choose 'y' for yes, or 'n' for no."
}
do {
$playerchoice = Read-host "Enter your guess"
} while (([System.Enum]::GetValues([System.ConsoleColor])) -notcontains $playerchoice) {
if ($playerchoice -eq $cpuchoice ) {
Write-Host "You win, my favorite color is $cpuchoice." -ForegroundColor $cpuchoice; ''
$playerwins = $playerwins + 1
$totalguesses = $totalguesses + 1
}
elseif ($playerchoice -ne $cpuchoice ) {
Write-Host "You lose, try again."; ''
$playerguesses += $playerchoice
$playerguesses = $playerguesses.Split(',')
$totalguesses = $totalguesses + 1
Write-Host "Here are your guesses so far: "
$playerguesses
''
}
$round = $round + 1
}
until($playerwins -eq 1) {
$playergames = $playergames + 1
Write-Host "You've won this round and have won $playergames games." -ForegroundColor Green
Write-Host "Your total guesses: $totalguesses."
Write-Host "Your wins - $playergames" -ForegroundColor Yellow
Write-Host "Computer wins - $compgames" -ForegroundColor Yellow
''
}
$playagain = Read-Host "I enjoyed this game. Would you like to challenge again, $name? Y or N"
while (("y", "n") -notcontains $playagain) {
if ($playagain -eq "y") {
Write-Host "I look forward to our next battle!"; ''
$playerwins = 0
$compwins = 0
$game = $game + 1
}
elseif ($playagain -eq "n") {
Write-Host "Thank you for playing!"
exit
}
}
}
}
The do loop that causes the error is the one that starts with "Write-Host "Round $round!" after the first while statement.
Any help is appreciated! Thanks!
Your program is being parsed like this:
while ($playagain -eq 'y')
{
# do loop #1
do
{
# do loop #2
do {
}
while (([System.Enum]::GetValues([System.ConsoleColor])) -notcontains $playerchoice)
# floating script block #1
# (doesn't execute the scriptblock, but it gets sent to the output stream instead)
{
if ($playerchoice -eq $cpuchoice ) {
... etc ...
}
# try to invoke a cmdlet "until" with 2 parameters
# i.e. ($playerwins -eq 1) and { ... }
until ($playerwins -eq 1) {
$playergames = $playergames + 1
... etc ...
}
# while loop #1
while (("y", "n") -notcontains $playagain) {
...
}
}
}
The error is telling you the first do (do loop #1) doesn't have a trailing while or until.
There's no clear and simple fix I can offer to make your code run short of a significant rework because there's a number of issues (e.g. the floating script block #1, the dangling until and the while \ until-less do), but that's what the current error is saying anyway...
I have the next code written in PowerShell.
When I run the code, the Menu is shown, I enter the option 1..9 and the selected option is not called, the menu is shown again and again(see the screenshot).
When I enter an option I want to be called that function related to each option entered then to display the message "The function has been called" and also to display the menu to enter a new option. (see the scrennshot - code in C++)
Any idea ?
function PORII
{
Write-Host " PORII was called"
}
function DXD-BODY
{
Write-Host " DXD BODY was called"
}
function DXD-PAINT
{
Write-Host " DXD PAINT was called"
}
function DXD-PTO
{
Write-Host " DXD PTO was called"
}
function DXD-TCF
{
Write-Host " DXD TCF was called"
}
function FIS-SERVERS
{
Write-Host " FIS SERVERS was called"
}
function SERVERS
{
Write-Host " SERVERS was called"
}
function Acronis
{
Write-Host " Acronis was called"
}
function Menu
{
param([string]$Title = 'Menu')
Write-Host " ==================== $Title ==================== "
while (1)
{
Clear-Host
Write-Host " Press 1 for PORII: "
Write-Host " Press 2 for DXD BODY: "
Write-Host " Press 3 for DXD PAINT: "
Write-Host " Press 4 for DXD PTO: "
Write-Host " Press 5 for DXD TCF: "
Write-Host " Press 6 for FIS SERVERS: "
Write-Host " Press 7 for SERVERS: "
Write-Host " Press 8 for Acronis Images: "
Write-Host " Press 9 for Exit: "
$a = Read-Host -Prompt "`n Enter your option "
if (($a -eq 1) -or ($a -eq 2) -or ($a -eq 3) -or ($a -eq 4) -or ($a -eq 5) -or ($a -eq 6) -or ($a -eq 7) -or ($a -eq 8) -or ($a -eq 9))
{
switch($a)
{
1{PORII}
2{DXD-BODY}
3{DXD-PAINT}
4{DXD-PTO}
5{DXD-TCF}
6{FIS-SERVERS}
7{SERVERS}
8{Acronis-Images}
9{Exit}
}
}
else
{
continue
}
}
}
Menu
Your functions are being called, but that isn't obvious because Clear-Host is called right after, discarding the called function's output.
Apart from that, your code can be streamlined:
Instead of the if (($a -eq 1) -or ($a -eq 2) ... conditional, you can add a default branch to your switch statement.
Also note that Read-Host always returns a string, whereas your conditionals operate on numbers; thanks to PowerShell's automatic type conversions, this isn't a problem in your particular case (with explicit or implied equality comparison), but it's something to keep in mind.
Through the use of a hash table you can simplify your function while making it easier to maintain.
Function Menu {
param([string]$Title = 'Menu')
while ($TRUE) {
$OptionHT = #{
1="PORII"
2="DXD-BODY"
3="DXD-PAINT"
4="DXD-PTO"
5="DXD-TCF"
6="FIS-SERVERS"
7="SERVERS"
8="Acronis-Images"
9="Exit"
}
Write-Host " ==================== $Title ==================== "
For ($Cntr = 1 ; $Cntr -lt $($OptionHT.Count) + 1; $Cntr++) {
Write-Host "Press $Cntr for $($OptionHT.$($Cntr)):"
}
$a = Read-Host -Prompt "`n Enter your option "
If (($a.length) -eq 1 -and ([byte][char]$a) -ge 49 -and
([byte][char]$a) -le 57) {
& ($OptionHT.[int]$a)
}
} # End While ($True)
} # End Function Menu
By placing your options in the hash table you only have a single point to make changes for called function names.
The if statement vs switch eliminates any value other than a single single number from 1 to 9 (note use of ASCII values to verify number input) from being processed. And since we have eliminated invalid inputs a single statement can be used to search the hash table for the function to execute.
UPDATE: Per the comments below you'll have to either trap the EXIT (9) with an If statement and exit or Create another Function and call it something like Exit-Program and place the Exit command there, I tested a function and it works.
Note: I didn't clear the console between writes of the menu so you could see your selection as mentioned in the comments you can add it where you deem necessary.
HTH
$q = 0
do {
$a = write-input "enter value"
switch ($a) {
1.{ some option }
2.{}
default {}
}
} while ($a -gt $q)
In the above code, if we give $a=$null value then switch terminates from while loop. Please help me out to skip null checking and to continue in the loop.
As Ansgar Wiechers points out in the comments, the comparison $null -gt 0 is False. This terminates your While loop. You could update your while statement to while ($a -eq $null -or $a -gt $q)
Another alternative would be use a recursive function,
function Example-Function {
switch (Read-Host "Enter Value") {
1 { "Option 1"; Example-Function }
2 { "Option 2"; Example-Function }
default { "Invalid Option, Exiting" }
}
}
I am trying to validate a simple powershell input. I want to allow the number zero as valid input, but blank (just pressing enter) is not valid input. I am having the most difficult time with the validation. Everything works EXCEPT when the user enters the number zero.
I have tried checking the length, checking for null, etc.
Consider the code below.
If you enter 0 (zero) the output is the same as if you just press [enter] (no input)
Pick a number 0-6: 0
You picked 0
blank input
equals zero
too short
$OUchoice = -1
do
{
try{
$OUchoice = Read-Host "Pick a number 0-6"
}
catch{
write-host "invalid input"
}
Write-Host "You picked $OUchoice"
if ($OUchoice -gt 6) {write-host "too high"}
if ($OUchoice -lt 0) {write-host "too low"}
if ($OUchoice -eq "") {write-host "blank input"}
if ($OUchoice -eq 0 ) {write-host "equals zero"}
if ($OUchoice -eq $null ) {write-host "Null"}
if (!($OUchoice)) {write-host "too short"}
}
until (($OUchoice -ge 0) `
-and ($OUchoice -le 6) `
-and (($ouchoice)))
write-host "OK"
I have tried -eq $NULL and -eq "". What is the proper way to allow zero and disallow blank input?
Problem lies in this:
PS> 0 -eq ""
True
When two values of different type are compared second argument is casted to the type of the first. Unfortunately for you:
PS> [int]""
0
empty string when casted to int produces 0. In your case fix is easy: just reverse the order of operands as 0 casted to string would end up being '0':
if ("" -eq $OUchoice) {write-host "blank input"}
This is what I came up with. I ensure that the $OUChoice is an Int when you compare it against other numbers. This ensures that null input is a 0 and also allows for negative values.
$OUchoice = -1
do
{
try{
$OUchoice = Read-Host "Pick a number 0-6"
}
catch{
write-host "invalid input"
}
Write-Host "You picked $OUchoice"
Switch ($OUchoice) {
{
[string]::IsNullOrEmpty($OUchoice)} {
write-host "Null Input"
Break
}
{
[int]$OUchoice -gt 6} {
write-host "too high"
Break
}
{
[int]$OUchoice -lt 0} {
write-host "too low"
Break
}
{
[int]$OUchoice -eq 0 } {
write-host "equals zero"
Break
}
}
}
until (([int]$OUchoice -ge 0) -and ([int]$OUchoice -le 6) -AND (-NOT [string]::IsNullOrEmpty($OUchoice)))
write-host "OK"
Nest your ifs (I didn't test much, but did check the zero and blank cases):
if (-not ($OUchoice -eq ""))
{
if ($OUchoice -gt 6) {write-host "too high"}
if ($OUchoice -lt 0) {write-host "too low"}
if ($OUchoice -eq 0 ) {write-host "equals zero"}
if ($OUchoice -eq $null ) {write-host "Null"}
if (!($OUchoice)) {write-host "too short"}
}
else
{
Write-Output "blank input"
}
Output:
PS C:\users\mattp_000> .\x.ps1
Pick a number 0-6:
You picked
blank input
Pick a number 0-6: 0
You picked 0
equals zero
OK
PS C:\users\mattp_000> .\x.ps1
Pick a number 0-6: 3
You picked 3
OK
PS C:\users\mattp_000>
I would like to print a number in green if it's 100 or red if less, but this is not working
Write-Host -ForegroundColor { (if ($number -eq 100) {Green} else
{Red}) } "$number"
How can I do this without having
if (...) {Write-Host ...} else {Write-Host ...}
Try it like this:
Write-Host $number -ForegroundColor $(if ($number -eq 100) {'Green'} else {'Red'})
You don't want to use {} in this case. ForegroundColor does not accept a scriptblock and it is not pipeline bound. Besides you're not piping anything into Write-Host. A subexpression $() allows you to evaluate statements like if, foreach, etc.