Question

I am new to power shell. I am trying to use the function like the goto in batch files.

In my script where I have$input1 = Read-Host "Please select an option 1, 2, 3. " I want to Clear-Host and restart script if the use does not enter 1, 2, 3.

Write-Host 1. Convert Byte to Megabyte.
Write-Host
Write-Host 2. Convert Byte to Gigabyte.
Write-Host
Write-Host 3. Conver Byte to Terabyte.

#
#
# Assign value to the variables
#

$b2MB = '1048576'
$b2GB = '1073741824'
$b2TB = '1099511627776'

$input1 = ""

#
#
# prompts user for input from the main screen.
#
$input1 = Read-Host "Please select an option 1, 2, 3. "

#
#
# Depending on what the user input will execute a certain conversion.
#
#

if ( $input1 -eq 1 ) {
$mb2 = Read-Host " Enter how many bytes you want to convert to Megabytes? "
$bytesToMb = $mb2 / $b2MB
Write-Host $mb2 'is equal to '$bytesToMb' Megabytes'
} elseif ($input1 -eq  2) {
$mb3 = Read-Host " Enter how many bytes you want to convert to Gigabytes? "
$bytesToGb = $mb3 / $b2GB
Write-Host $mb3 'is equal to '$bytesToGb' Gigabytes'
} elseif ( $input1 -eq 3) {
$mb4 = Read-Host " Enter how many bytes you want to convert to Terabytes? "
$bytesToTb = $mb4 / $b2TB
Write-Host $mb4 'is equal to '$bytesToTb' Terabytes'
} else {
Write-Host " You have entered an invalid option. "
}
Was it helpful?

Solution

I believe you want something like this:

# Start a continuous loop
while ($true) {

    # Write messages
    Write-Host 1. Convert Byte to Megabyte.
    Write-Host
    Write-Host 2. Convert Byte to Gigabyte.
    Write-Host
    Write-Host 3. Conver Byte to Terabyte.

    # Get the input
    $input1 = Read-Host "Please select an option 1, 2, 3. "

    # See if the input equals 1, 2, or 3.  If so, break the loop.
    if (1..3 -contains $input1) { break }

    # If we get here, then the input was bad.
    # So, we clear the host and let the loop start-over
    Clear-Host
}

#
#
# Assign value to the variables
#

$b2MB = '1048576'
$b2GB = '1073741824'
$b2TB = '1099511627776'

#
#
# Depending on what the user input will execute a certain conversion.
#
#

if ( $input1 -eq 1) {
    $mb2 = Read-Host " Enter how many bytes you want to convert to Megabytes? "
    $bytesToMb = $mb2 / $b2MB
    Write-Host $mb2 'is equal to '$bytesToMb' Megabytes'
} elseif ($input1 -eq  2) {
    $mb3 = Read-Host " Enter how many bytes you want to convert to Gigabytes? "
    $bytesToGb = $mb3 / $b2GB
    Write-Host $mb3 'is equal to '$bytesToGb' Gigabytes'
} elseif ( $input1 -eq 3) {
    $mb4 = Read-Host " Enter how many bytes you want to convert to Terabytes? "
    $bytesToTb = $mb4 / $b2TB
    Write-Host $mb4 'is equal to '$bytesToTb' Terabytes'
} else {
    Write-Host " You have entered an invalid option. "
}

OTHER TIPS

Easy enough, use a Do/Until loop.

#
#
# Assign value to the variables
#

$input1 = ""

# Start the loop to get the user's choice (with validation)
Do{
    cls
    Write-Host 1. Convert Byte to Megabyte.
    Write-Host
    Write-Host 2. Convert Byte to Gigabyte.
    Write-Host
    Write-Host 3. Conver Byte to Terabyte.

    #
    #
    # prompts user for input from the main screen.
    #
    $input1 = Read-Host "Please select an option 1, 2, 3. "
}Until(@(1,2,3) -contains $input1)

Switch($input1){
    1 {Read-Host "Enter how many bytes you want to convert to Megabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Megabytes" -f [double]$_,($_/1MB);Write-Host "$Out"}}
    2 {Read-Host "Enter how many bytes you want to convert to Gigabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Gigabytes" -f [double]$_,($_/1GB);Write-Host "$Out"}}
    3 {Read-Host "Enter how many bytes you want to convert to Terabytes? "|%{$Out = "{0:N} bytes is equal to {1:n4} Terabytes" -f [double]$_,($_/1TB);Write-Host "$Out"}}
}

I also used a Switch instead of a bunch of If/Then statements, and did the math with ###/1MB or /1GB or /1TB since Powershell can do that calculation for you.

Edit: Oh yeah, I also formatted the numbers. Adding commas makes it easier to read large numbers, and I truncated the calculated value to 4 places past the decimal. That can be changed by altering the 4 in {1:n4} to whatever you want the decimal to go to, or remove the 4 to include everything. If you make it a large decimal it will fill with zeros if that many do not exist. Such as 4.23 when formatted through {1:n5} comes out as 4.23000 since it has to have 5 places past the decimal.

Ok, the Switch loop is used instead of nested if statements like you were using. The syntax is

Switch(array to parse) { Value or scriptblock {action to perform on match} Different value or scriptblock {action to perform on match} } So in your case there is only one thing that we are parsing, and that is the users selection. So let's say they choose 2 to convert to Gigabytes. $input2 = 2. Switch starts comparisons at the top, and checks if the value is 1. It is not so it moves to the next line. It checks to see if the value is 2. It is, so the switch command performs the actions in the accompanying scriptblock there. We will get to that in a moment. After it finished that scriptblock it moves to the next line and checks if the value is 3. It is not, and that was the last option so it finishes that loop. There is not another value to parse since $input2 only had one value so it exits the switch loop. Switch works on arrays so there could have potentially have been more things to compare against the three options in the switch loop.

That is the switch loop. Let's look at the scriptblock that it ran when the value matched up for the second option. I'll break it down a bit here...

Read-Host "Enter how many bytes you want to convert to Gigabytes? "|
%{
    $Out = "{0:N} bytes is equal to {1:n4} Gigabytes" -f [double]$_,($_/1GB);
    Write-Host "$Out"
}

That first line is pretty much yours if I remember right, but instead of storing the value in a variable for use later I pipe it to a for each loop (%{...} is short for foreach{...}). Then, since write-host doesn't really allow formatting I do some formatting and save the string in $out. So this is where it might get intimidating. "{0:N}" works with the -f which is short for -format. It works like a place holder that says to look at the -f command at the end of the string and get the first thing provided to it (arrays in powershell start at record 0, so usually a reference to item 0 is looking for the first item). Once it gets that first value that follows the -f it applies the formatting specified after the colon N which means it formats it like a number putting a comma every three digits.

Ok, there is some text in there and then {1:N4} which is another formatting placeholder. The part before the colon specifies which item to fetch, and since 0 was the first value to be formatted, 1 must be the second. So it gets the second value and applies the formatting after the colon. N4 again says it is a number, but specifies to only show the first 4 numbers past the decimal.

Then it has the -f which says that there are some things to format. The first item is $_ which is the value that the user entered which was piped into the foreach loop. The [double] before it specifies the type of object it is. Double is a kind of number, like int32 or hex, but it has very loose guidelines so the user can enter very large values and not have issues. That gets passed directly to the first placeholder. Then comes $_/1GB which is the number that the user entered divided by Gigabytes, because powershell has that ability built in. It finds the result of that and passes it to the second placeholder. So now we have the text that we want to pass back to the user, with the numbers nicely formatted and easy to read, and stored that string into $out. Last thing in that scriptblock is to write $out to the host.

Now you may ask why I had to specify that $_ as a [double] the first time, but not the second. The reason is that the second time I was performing math on it, so powershell figures that it must be a number if I'm dividing it, so I don't have to declare it there.

I hope that makes the script make more sense now.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top