Powershell Do Until Loop - powershell

$StartID = Read-Host -Prompt "StartID"
$StopID = Read-Host -Prompt "StopID"
$i = $StartID
do {
Write-Host $startID
Write-Host $StopID
$i = ($StartId + 1)
} until ($i -gt $StopID)
The first problem is that after the statement $i = $startid + 1, the $i equals 11 and not 2.
The second problem is that even though the until statement says that it should stop when $i -gt $stop the loop continues forever.
How do I get the $i to increase by 1 and not 10 and how do I stop the loop when $i -gt $stop.

Read-Promptreturns a string per default (this stackoverflow answer explains different ways for conversion). You've to convert/cast the string to a numeric value:
[int]$start = Read-Host -Prompt "Start"
[int]$stop = Read-Host -Prompt "Stop"
do {
Write-host $start
$start++
} until ($start -ge $stop)
Hope that helps.

Related

Why Write-Verbose messages don't appear from conditions

I'm trying to receive Verbose messages of every sorting step and run my script with -Verbose key, but I don't receive any verbose message from the conditionals (loops). I receive my messages only if I call them outside the conditionals. Please help
[CmdletBinding()]
param()
set-location "\test folder"
$listOfItems = Get-ChildItem | Select-Object -Property Name, Mode, LastWriteTime, #{label = "FileSize (MB)";expression = {$_.Length/1024/1024}}
$bufferItem = 0
for ($i = $listOfItems.Length - 1; $i -eq 0; $i--) {
for ($j = 0; $i -lt $i; $j++) {
if ($listOfItems[$j]."FileSize (MB)" -gt $listOfItems[$j + 1]."FileSize (MB)") {
Write-Verbose -Message "Transfer the value of the buffer variable to the element below the list"
continue
}
elseif ($listOfItems[$j]."FileSize (MB)" -lt $listOfItems[$j + 1]."FileSize (MB)") {
$bufferItem = $listOfItems[$j]
$listOfItems[$j] = $listOfItems[$j + 1]
$listOfItems[$j + 1] = $bufferItem
}
Write-Verbose -Message "Transfer the value of the buffer variable to the element below the list"
}
}
There's a bug in your inner loop condition:
for ($j = 0; $i -lt $i; $j++) {
Since $i -lt $i will never evaluate to $true, the inner loop body won't ever execute, and no Write-Verbose statement is ever reached.
Fix the loop condition and you'll find Write-Verbose works perfectly fine in conditional statements.

Finding Middle Number in PowerShell

I am practicing in PowerShell and am making a user response input where one of the options is to input 3 numbers, and the program will return the middle number. I have done this a million times and it seems I cannot get it to return the middle number consistently.
For example when my numbers are 1, 23452342 and 3, it says that 3 is the middle number.
Here is my code:
if ($response -eq 1) {
$a = Read-Host "Enter a number "
$b = Read-Host "Enter a second number "
$c = Read-Host "Enter a third number "
if (($a -gt $b -and $a -lt $c) -or ($a -lt $b -and $a -gt $c)) {
Write-Host "$a is the middle number"
}
if (($b -gt $a -and $b -lt $c) -or ($b -gt $c -and $b -lt $a)) {
Write-Host "$b is the middle number"
}
if (($c -gt $a -and $c -lt $b) -or ($c -gt $b -and $c -lt $a)) {
Write-Host "$c is the middle number"
}
}
Instead of doing a number of individual comparisons simply sorting the three values and picking the second element will give you the median right away. But I suspect what's actually messing up the results for you is that Read-Host returns strings when you need them to be numeric values. Sort order of strings ("1" < "20" < "3") is different from numeric sort order (1 < 3 < 20), because characters at corresponding positions are compared rather than the whole number.
Casting the entered values to integers (or doubles if you expect floating point numbers) should resolve the issue:
if ($response -eq 1) {
[int]$a = Read-Host 'Enter a number'
[int]$b = Read-Host 'Enter a second number'
[int]$c = Read-Host 'Enter a third number'
$n = ($a, $b, $c | Sort-Object)[1]
Write-Host "$n is the median."
}
As an additional solution that would work on any array where u need the middle item you could just solve it like this:
$arr = 1..50
($arr | Sort-Object)[[int](($arr.count -1) /2)]
If your array comes in a format that does not need the sorting, just leave this part out.
edit: Obviously you would have to insert the data into an array on the first step.
Best regards

PowerShell guessing game max number of guesses

Hi I have made a number guessing game, but I struggle to make the game stop after a x guesses.
$Number = (Get-Random 100) + 1
$Guess = 0
$count = 1
Write-Host "I'm thinking of a number between 1 and 100."
While ($Number -ne $Guess) {
Write-Host -NoNewline "What is the number? "
$Guess = [int] (Read-Host)
If ($Guess -gt $Number) { Write-Host "$Guess is too high." }
If ($Guess -lt $Number) { Write-Host "$Guess is too low." }
If ($count -eq 7) {break}
}
Write-Host "Correct! $Number is the number I was thinking!"
I've added a variable into your while loop, named $Tries it increments itself by one everytime someone guesses a number, until it equals 10, then the loop breaks.
Next to that, I've included the line that tells you that the number is correct within the loop and tell it to display the correct message and break the loop when the number is correct.
I had to include this in the loop because if I would just let it break the loop when $Tries was bigger than 10 it would still display the message stating that the number was correct.
$Number = (Get-Random 100) + 1
$Guess = 0
$Tries = 0
Write-Host "I'm thinking of a number between 1 and 100."
While ($Number -ne $Guess) {
Write-Host -NoNewline "What is the number? "
$Guess = [int] (Read-Host)
$Tries = $Tries + 1
If ($Tries -gt 10) { Write-Host "You have used all of your guesses, try again." ; break }
If ($Guess -gt $Number) { Write-Host "$Guess is too high." }
If ($Guess -lt $Number) { Write-Host "$Guess is too low." }
If ($Guess -eq $Number) { Write-Host "Correct! $Number is the number I was thinking!" ; break}
}

Using the Get-Date cmdlet

I am taking a scripting class as part of my IT degree and I am stumped on my powershell script. I have to use Get-Date to time how long my game is played, and also create a log file that stores number of games played, and the shorted and longest games played. The log file must be created outside the script, but must update within the script. I put the code I have so far below.
$rand = new-object system.random
$number= $rand.next(0,11)
clear-host
do{ $a = read-host -prompt "enter number between 1 and 10"
if ($a -gt $Number) {Write-Host "number is too high"}
elseif ($a -lt $Number) {Write-Host "number is too low"}
elseif ($a -eq $Number) {Write-Host "You did it!! It took you $x tries!"}
else {"You have to guess a number!!!"}
$x = $x + 1
} while ($a -ne $number)
$path = C:\temp\logfile.log.txt
To time execution, grab the date before and after you've done your work, and then subtract the two to get a TimeSpan representing the time it took
$StartTime = Get-Date
# script goes here
$EndTime = Get-Date
$TimeTaken = $EndTime - $StartTime
Write-Host "A total of $($TimeTaken.TotalSeconds) has passed"
You could also use the StopWatch class to accomplish this:
$Watch = [System.Diagnostics.Stopwatch]::StartNew()
# script goes here
$Watch.Stop()
$TimeTaken = $Watch.Elapsed
Write-Host "A total of $($TimeTaken.TotalSeconds) has passed"

Dynamic input array Powershell

once again I contact you because I am once again having problems with a Powershell script assignment.
My current assignement is to make a script that lets a user put in 1-10 values. The values have to be positive numbers. After that I have to calculate an average of an array.
My idea in this was the following:
clear-host
$averageArray = #()
Write-Host "How many numbers do you want to put in?" -for yellow
Write-Warning "Maximum is 10!"
Write-Host "Press the Enter key to continue."
$amountValues = Read-host
while($amountVAlues -notmatch "^([1-9]|[1][0])$") {
$amountValues = Read-Host "Please enter a number between 1 and 10"
if($amountVAlues -notmatch "^([1-9]|[1][0])$") {Write-host "Error! Please enter a number between 1 and 10!"}
}
$value1 = read-host "Enter number one"
while($value1 -notmatch '^\d+$') {
$value1 = Read-Host
if($value1 -notmatch '^\d+$') {Write-host "Error! Please enter a positive number!"}
}
$value2 = read-host "Enter number two"
while($value2 -notmatch '^\d+$') {
$value2 = Read-Host
if($value2 -notmatch '^\d+$') {Write-host "Error! Please enter a positive number!"}
}
$averageArray = $averageArray + $value1
write-host "$averageArray"
read-host
I created an array, and made the user input a number between 1-10 for the amount of total $values they want in the array. After that I wanted to loop the input of a $value, and input it in the array. I wanted to loop it as many times as the $amountValues variable.
Problem with doing this is that if I would loop it, $variable1 would get overwritten an 'x' amount of times.
Is there any way to input the values via a loop into the array?
I'ld do it like this:
while ( (1..10) -notcontains $g)
{
$g = read-host "How many numbers do you want to put in? (value from 1 to 10) "
}
$ar=#()
for ($i=0; $i -lt $g; $i++)
{
$ar += read-host "Enter value $($i+1)"
}
$averageArray = ($ar | Measure-Object -Average).average
write-host "Average is : $averageArray"