In this article we are going to discuss basics of how to control code execution in a PowerShell script. There are several keywords, which have slightly different behavior: break
, return
and exit
. To help you better understand what is going on, I will post all code blocks tagged with Powershell, immediately followed by its text output.
Break
Just as in C++, you can use break
to exit loops early:
1
2
3
4
5
6
7
8
| #Sample 1. Break a FOR loop
for($i=0; $i -lt 5; $i++)
{
Write-Host "Start iteration $i"
if($i -eq 2) { Write-Host "Break"; break }
Write-Host "Finish iteration $i"
}
Write-Host "End of script reached!" #will be executed
|
1
2
3
4
5
6
7
| Start iteration 0
Finish iteration 0
Start iteration 1
Finish iteration 1
Start iteration 2
Break
End of script reached!
|
In this scenario, whatever is written after the for
loop will be executed. The most important thing to understand is that it gets you up exactly one structural level, no matter where in the code you are. Have a look at the following samples:
1
2
3
4
| #Sample 2. Break a script
Write-Host "Line1"
break
Write-Host "Line2" #this line will not executed
|
1
2
3
4
5
6
7
8
| #Sample 3. Break a pipeline (incorrect BREAK usage)
#Task: print numbers 1 through 5, stop when current number is greater than 2
1..5 | % {
Write-Host "Start iteration $_"
if($_ -gt 2) { Write-Host "Break"; break }
Write-Host "Finish iteration $_"
}
Write-Host "End of script reached!" #not gonna work, read explanation below
|
1
2
3
4
5
6
| Start iteration 1
Finish iteration 1
Start iteration 2
Finish iteration 2
Start iteration 3
Break
|
We have come up to an interesting point. For some reason, break
statement put inside a foreach
pipeline ’thinks’ it’s being executed outside the pipeline, so in Sample 3 it will exit the script. In other words, if you put a line after 1..5
loop, it will not be executed.
There is a workaround, however. Just rewrite your code to use a simple foreach
loop and not a pipeline. For Sample 3, the new code will look similar to this:
1
2
3
4
5
6
7
8
| #Sample 4. Break a FOREACH loop (correct BREAK usage)
#Task: print numbers 1 through 5, stop when current number is greater than 2
foreach ( $number in 1..5 ) {
Write-Host "Start iteration $number"
if($number -gt 2) { break }
Write-Host "Finish iteration $number"
}
Write-Host "End of script reached!" #will run perfectly
|
1
2
3
4
5
6
| Start iteration 1
Finish iteration 1
Start iteration 2
Finish iteration 2
Start iteration 3
End of script reached!
|
Return
Let’s start with Sample 1 and put return
statement instead of break
:
1
2
3
4
5
6
7
8
| #Sample 5. Return from a FOR loop
for($i=0; $i -lt 5; $i++)
{
Write-Host "Start iteration $i"
if($i -eq 2) { Write-Host "Return"; return }
Write-Host "Finish iteration $i"
}
Write-Host "End of script reached!" #will NOT be executed
|
1
2
3
4
5
6
| Start iteration 0
Finish iteration 0
Start iteration 1
Finish iteration 1
Start iteration 2
Return
|
In this case we get same results, however everything after the loop is not executed, because the program goes up one functional level, which includes functions, pipelines and, of course, scripts. Ordinary loops do not count. Take a look at previous samples, changed to return
:
1
2
3
4
| #Sample 6. Return from a script
Write-Host "Line1"
return
Write-Host "Line2" #this line will not executed, same as before
|
Because functional and structural levels are one thing here (=script), behavior is the same for return
or break
. The following example illustrates how return
works for pipelines. Remember, each pipeline iteration is a functional level in terms of PowerShell, so by doing return
you only exit current iteration.
1
2
3
4
5
6
7
8
| #Sample 7. Return from a pipeline
#Task: print numbers 1 through 5, skip when current number is greater than 2
1..5 | % {
Write-Host "Start iteration $_"
if($_ -gt 2) { Write-Host "Return"; return }
Write-Host "Finish iteration $_"
}
Write-Host "End of script reached!" #will be executed
|
1
2
3
4
5
6
7
8
9
10
11
| Start iteration 1
Finish iteration 1
Start iteration 2
Finish iteration 2
Start iteration 3
Return
Start iteration 4
Return
Start iteration 5
Return
End of script reached!
|
1
2
3
4
5
6
7
8
| #Sample 8. Return from a FOREACH loop
#Task: print numbers 1 through 5, stop when current number is greater than 2
foreach ( $number in 1..5 ) {
Write-Host "Start iteration $number"
if($number -gt 2) { return }
Write-Host "Finish iteration $number"
}
Write-Host "End of script reached!" #will not be executed
|
1
2
3
4
5
| Start iteration 1
Finish iteration 1
Start iteration 2
Finish iteration 2
Start iteration 3
|
Exit
This appears to be most simple. exit
works on the script level, regardless of where it’s put. While being less flexible, it is often used as emergency action to stop script execution when exception takes place. You might wanna use it when you need to quit your complicated script structure, if results are available early.
I will update this article as I progress on this topic and will probably post more code samples.