11---
22description : PowerShell provides methods to create loops, make decisions, and logically control the flow of code in scripts.
33ms.custom : Contributor-mikefrobbins
4- ms.date : 12/08/2022
4+ ms.date : 3/20/2025
55ms.reviewer : mirobb
66title : Flow control
77---
8+
89# Chapter 6 - Flow control
910
1011## Scripting
1112
12- When you move from writing PowerShell one-liners to writing scripts, it sounds a lot more
13- complicated than it really is. A script is nothing more than the same or similar commands that you
14- would run interactively in the PowerShell console, except they're saved as a ` .PS1 ` file. There are
15- some scripting constructs that you may use such as a ` foreach ` loop instead of the ` ForEach-Object `
16- cmdlet. To beginners, the differences can be confusing especially when you consider that ` foreach `
17- is both a scripting construct and an alias for the ` ForEach-Object ` cmdlet.
13+ When you move from writing PowerShell one-liners to writing scripts, it sounds more complicated than
14+ it is. A script is nothing more than the same or similar commands you run interactively in the
15+ PowerShell console, except you save them as a ` .PS1 ` file. There are some scripting constructs that
16+ you might use, such as a ` foreach ` loop instead of the ` ForEach-Object ` cmdlet. The differences can
17+ be confusing for beginners when considering that ` foreach ` is both a scripting construct and an
18+ alias for the ` ForEach-Object ` cmdlet.
1819
1920## Looping
2021
21- One of the great things about PowerShell is, once you figure out how to do something for one item,
22- it's almost as easy to do the same task for hundreds of items. Simply loop through the items using
23- one of the many different types of loops in PowerShell.
22+ One of the best aspects of PowerShell is its scalability. Once you learn how to perform a task for a
23+ single item, applying the same action to hundreds of items is almost as straightforward. Loop
24+ through the items using one of the different types of loops in PowerShell.
2425
2526### ForEach-Object
2627
27- ` ForEach-Object ` is a cmdlet for iterating through items in a pipeline such as with PowerShell
28+ ` ForEach-Object ` is a cmdlet for iterating through items in a pipeline, such as with PowerShell
2829one-liners. ` ForEach-Object ` streams the objects through the pipeline.
2930
30- Although the ** Module** parameter of ` Get-Command ` accepts multiple values that are strings , it only
31- accepts them via pipeline input by property name or via parameter input. In the following scenario,
32- if I want to pipe two strings by value to ` Get-Command ` for use with the ** Module** parameter, I
33- would need to use the ` ForEach-Object ` cmdlet.
31+ Although the ** Module** parameter of ` Get-Command ` accepts multiple string values , it only accepts
32+ them via pipeline input by property name or parameter input. In the following scenario, if you want
33+ to pipe two strings by value to ` Get-Command ` for use with the ** Module** parameter, you would need
34+ to use the ` ForEach-Object ` cmdlet.
3435
3536``` powershell
3637'ActiveDirectory', 'SQLServer' |
37- ForEach-Object {Get-Command -Module $_} |
38- Group-Object -Property ModuleName -NoElement |
39- Sort-Object -Property Count -Descending
38+ ForEach-Object {Get-Command -Module $_} |
39+ Group-Object -Property ModuleName -NoElement |
40+ Sort-Object -Property Count -Descending
4041```
4142
4243``` Output
@@ -47,16 +48,16 @@ Count Name
4748```
4849
4950In the previous example, ` $_ ` is the current object. Beginning with PowerShell version 3.0,
50- ` $PSItem ` can be used instead of ` $_ ` . But I find that most experienced PowerShell users still
51- prefer using ` $_ ` since it's backward compatible and less to type.
51+ ` $PSItem ` can be used instead of ` $_ ` . Most experienced PowerShell users prefer using ` $_ ` since
52+ it's backward compatible and less to type.
5253
53- When using the ` foreach ` keyword, you must store all of the items in memory before iterating through
54- them, which could be difficult if you don't know how many items you're working with.
54+ When using the ` foreach ` keyword, you must store the items in memory before iterating through them,
55+ which could be difficult if you don't know how many items you're working with.
5556
5657``` powershell
5758$ComputerName = 'DC01', 'WEB01'
5859foreach ($Computer in $ComputerName) {
59- Get-ADComputer -Identity $Computer
60+ Get-ADComputer -Identity $Computer
6061}
6162```
6263
@@ -82,28 +83,28 @@ SID : S-1-5-21-2989741381-570885089-3319121794-1107
8283UserPrincipalName :
8384```
8485
85- Many times a loop such as ` foreach ` or ` ForEach-Object ` is necessary. Otherwise you'll receive an
86- error message.
86+ Many times a loop such as ` foreach ` or ` ForEach-Object ` is necessary. Otherwise you receive an error
87+ message.
8788
8889``` powershell
8990Get-ADComputer -Identity 'DC01', 'WEB01'
9091```
9192
9293``` Output
9394Get-ADComputer : Cannot convert 'System.Object[]' to the type
94- 'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter 'Identity'.
95- Specified method is not supported.
95+ 'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter
96+ 'Identity'. Specified method is not supported.
9697At line:1 char:26
9798+ Get-ADComputer -Identity 'DC01', 'WEB01'
9899+ ~~~~~~~~~~~~~~~
99- + CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ParameterBindingExc
100- eption
101- + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirectory.Management
102- .Commands.GetADComputer
100+ + CategoryInfo : InvalidArgument: (:) [Get-ADComputer], Parame
101+ terBindingException
102+ + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirecto
103+ ry.Management .Commands.GetADComputer
103104```
104105
105- Other times, you can get the same results while eliminating the loop altogether . Consult the cmdlet
106- help to understand your options.
106+ Other times, you can get the same results while eliminating the loop. Consult the cmdlet help to
107+ understand your options.
107108
108109``` powershell
109110'DC01', 'WEB01' | Get-ADComputer
@@ -131,19 +132,19 @@ SID : S-1-5-21-2989741381-570885089-3319121794-1107
131132UserPrincipalName :
132133```
133134
134- As you can see in the previous examples, the ** Identity** parameter for ` Get-ADComputer ` only accepts a
135- single value when provided via parameter input, but it allows for multiple items when the input is
136- provided via pipeline input.
135+ As you can see in the previous examples, the ** Identity** parameter for ` Get-ADComputer ` only
136+ accepts a single value when provided via parameter input. It allows for multiple items when you
137+ provide the input via pipeline input.
137138
138139### For
139140
140- A ` for ` loop iterates while a specified condition is true. The ` for ` loop is not something that I
141- use often, but it does have its uses.
141+ A ` for ` loop iterates while a specified condition is true. I don't use the ` for ` loop often, but it
142+ has uses.
142143
143144``` powershell
144145for ($i = 1; $i -lt 5; $i++) {
145- Write-Output "Sleeping for $i seconds"
146- Start-Sleep -Seconds $i
146+ Write-Output "Sleeping for $i seconds"
147+ Start-Sleep -Seconds $i
147148}
148149```
149150
@@ -154,25 +155,26 @@ Sleeping for 3 seconds
154155Sleeping for 4 seconds
155156```
156157
157- In the previous example, the loop will iterate four times by starting off with the number one and
158- continue as long as the counter variable ` $i ` is less than 5. It will sleep for a total of 10
159- seconds.
158+ In the previous example, the loop iterates four times by starting with the number one and continuing
159+ as long as the counter variable ` $i ` is less than 5. It sleeps for a total of 10 seconds.
160160
161161### Do
162162
163163There are two different ` do ` loops in PowerShell. ` Do Until ` runs while the specified condition is
164164false.
165165
166+ The following example is a numbers game that continues until the value you guess equals the same
167+ number that the ` Get-Random ` cmdlet generated.
168+
166169``` powershell
167170$number = Get-Random -Minimum 1 -Maximum 10
168171do {
169- $guess = Read-Host -Prompt "What's your guess?"
170- if ($guess -lt $number) {
171- Write-Output 'Too low!'
172- }
173- elseif ($guess -gt $number) {
174- Write-Output 'Too high!'
175- }
172+ $guess = Read-Host -Prompt "What's your guess?"
173+ if ($guess -lt $number) {
174+ Write-Output 'Too low!'
175+ } elseif ($guess -gt $number) {
176+ Write-Output 'Too high!'
177+ }
176178}
177179until ($guess -eq $number)
178180```
@@ -185,20 +187,17 @@ Too low!
185187What's your guess?: 3
186188```
187189
188- The previous example is a numbers game that continues until the value you guess equals the same
189- number that the ` Get-Random ` cmdlet generated.
190-
191- ` Do While ` is just the opposite. It runs as long as the specified condition evaluates to true.
190+ ` Do While ` is the opposite. It runs as long as the specified condition is evaluated as true.
192191
193192``` powershell
194193$number = Get-Random -Minimum 1 -Maximum 10
195194do {
196- $guess = Read-Host -Prompt "What's your guess?"
197- if ($guess -lt $number) {
198- Write-Output 'Too low!'
199- } elseif ($guess -gt $number) {
200- Write-Output 'Too high!'
201- }
195+ $guess = Read-Host -Prompt "What's your guess?"
196+ if ($guess -lt $number) {
197+ Write-Output 'Too low!'
198+ } elseif ($guess -gt $number) {
199+ Write-Output 'Too high!'
200+ }
202201}
203202while ($guess -ne $number)
204203```
@@ -219,14 +218,19 @@ The same results are achieved with a `Do While` loop by reversing the test condi
219218
220219### While
221220
222- Similar to the ` Do While ` loop, a ` While ` loop runs as long as the specified condition is true. The
223- difference however, is that a ` While ` loop evaluates the condition at the top of the loop before any
224- code is run. So it doesn't run if the condition evaluates to false.
221+ Like the ` Do While ` loop, a ` While ` loop runs as long as the specified condition is true. The
222+ difference, however, is that a ` While ` loop evaluates the condition at the top of the loop before
223+ any code is run. So, it doesn't run if the condition is evaluated as false.
224+
225+ The following example calculates what day Thanksgiving Day is on in the United States. It's always
226+ on the fourth Thursday of November. The loop starts with the 22nd day of November and adds a day,
227+ while the day of the week isn't equal to Thursday. If the 22nd is a Thursday, the loop doesn't run
228+ at all.
225229
226230``` powershell
227231$date = Get-Date -Date 'November 22'
228232while ($date.DayOfWeek -ne 'Thursday') {
229- $date = $date.AddDays(1)
233+ $date = $date.AddDays(1)
230234}
231235Write-Output $date
232236```
@@ -235,38 +239,37 @@ Write-Output $date
235239Thursday, November 23, 2017 12:00:00 AM
236240```
237241
238- The previous example calculates what day Thanksgiving Day is on in the United States. It's always on
239- the fourth Thursday of November. So the loop starts with the 22nd day of November and adds a day
240- while the day of the week isn't equal to Thursday. If the 22nd is a Thursday, the loop doesn't run
241- at all.
242-
243242## Break, Continue, and Return
244243
245- ` Break ` is designed to break out of a loop. It's also commonly used with the ` switch ` statement.
244+ The ` break ` statement is designed to exit a loop and is often used with the ` switch ` statement. In
245+ the following example, ` break ` causes the loop to end after the first iteration.
246246
247247``` powershell
248248for ($i = 1; $i -lt 5; $i++) {
249- Write-Output "Sleeping for $i seconds"
250- Start-Sleep -Seconds $i
251- break
249+ Write-Output "Sleeping for $i seconds"
250+ Start-Sleep -Seconds $i
251+ break
252252}
253253```
254254
255255``` Output
256256Sleeping for 1 seconds
257257```
258258
259- The ` break ` statement shown in the previous example causes the loop to exit on the first iteration .
259+ ` Continue ` is designed to skip to the next iteration of a loop .
260260
261- Continue is designed to skip to the next iteration of a loop.
261+ The following example outputs the numbers 1, 2, 4, and 5. It skips number 3 and continues with the
262+ next iteration of the loop. Like ` break ` , ` continue ` breaks out of the loop except only for the
263+ current iteration. Execution continues with the next iteration instead of breaking out of the loop
264+ altogether and stopping.
262265
263266``` powershell
264267while ($i -lt 5) {
265- $i += 1
266- if ($i -eq 3) {
267- continue
268- }
269- Write-Output $i
268+ $i += 1
269+ if ($i -eq 3) {
270+ continue
271+ }
272+ Write-Output $i
270273}
271274```
272275
@@ -277,58 +280,56 @@ while ($i -lt 5) {
2772805
278281```
279282
280- The previous example will output the numbers 1, 2, 4, and 5. It skips number 3 and continues with
281- the next iteration of the loop. Similar to ` break ` , ` continue ` breaks out of the loop except only
282- for the current iteration. Execution continues with the next iteration instead of breaking out of
283- the loop and stopping.
283+ ` Return ` is designed to exit out of the existing scope.
284284
285- Return is designed to exit out of the existing scope.
285+ Notice that in the following example, return outputs the first result and then exits out of the
286+ loop.
286287
287288``` powershell
288289$number = 1..10
289290foreach ($n in $number) {
290- if ($n -ge 4) {
291- Return $n
292- }
291+ if ($n -ge 4) {
292+ Return $n
293+ }
293294}
294295```
295296
296297``` Output
2972984
298299```
299300
300- Notice that in the previous example, return outputs the first result and then exits out of the
301- loop. A more thorough explanation of the result statement can be found in one of my blog articles:
302- [ "The PowerShell return keyword"] [ "The PowerShell return keyword" ] .
301+ A more thorough explanation of the result statement can be found in one of my blog articles:
302+ [ The PowerShell return keyword] [ the-powershell-return-keyword ] .
303303
304304## Summary
305305
306- In this chapter, you've learned about the different types of loops that exist in PowerShell.
306+ In this chapter, you learned about the different types of loops that exist in PowerShell.
307307
308308## Review
309309
310- 1 . What is the difference in the ` ForEach-Object ` cmdlet and the foreach scripting construct?
311- 1 . What is the primary advantage of using a While loop instead of a Do While or Do Until loop.
312- 1 . How do the break and continue statements differ?
310+ 1 . What's the difference between the ` ForEach-Object ` cmdlet and the ` foreach ` scripting construct?
311+ 1 . What's the primary advantage of using a ` While ` loop instead of a ` Do While ` or ` Do Until ` loop?
312+ 1 . How do the ` break ` and ` continue ` statements differ?
313313
314- ## Recommended Reading
314+ ## References
315315
316- - [ ForEach-Object] [ ForEach-Object ]
317- - [ about_ForEach] [ about_ForEach ]
318- - [ about_For] [ about_For ]
319- - [ about_Do] [ about_Do ]
320- - [ about_While] [ about_While ]
321- - [ about_Break] [ about_Break ]
322- - [ about_Continue] [ about_Continue ]
323- - [ about_Return] [ about_Return ]
316+ - [ ForEach-Object] [ foreach-object ]
317+ - [ about_ForEach] [ about-foreach ]
318+ - [ about_For] [ about-for ]
319+ - [ about_Do] [ about-do ]
320+ - [ about_While] [ about-while ]
321+ - [ about_Break] [ about-break ]
322+ - [ about_Continue] [ about-continue ]
323+ - [ about_Return] [ about-return ]
324324
325325<!-- link references -->
326- [ ForEach-Object ] : /powershell/module/microsoft.powershell.core/foreach-object
327- [ about_ForEach ] : /powershell/module/microsoft.powershell.core/about/about_foreach
328- [ about_For ] : /powershell/module/microsoft.powershell.core/about/about_for
329- [ about_Do ] : /powershell/module/microsoft.powershell.core/about/about_do
330- [ about_While ] : /powershell/module/microsoft.powershell.core/about/about_while
331- [ about_Break ] : /powershell/module/microsoft.powershell.core/about/about_break
332- [ about_Continue ] : /powershell/module/microsoft.powershell.core/about/about_continue
333- [ about_Return ] : /powershell/module/microsoft.powershell.core/about/about_return
334- [ "The PowerShell return keyword" ] : https://mikefrobbins.com/2015/07/23/the-powershell-return-keyword/
326+
327+ [ foreach-object ] : /powershell/module/microsoft.powershell.core/foreach-object
328+ [ about-foreach ] : /powershell/module/microsoft.powershell.core/about/about_foreach
329+ [ about-for ] : /powershell/module/microsoft.powershell.core/about/about_for
330+ [ about-do ] : /powershell/module/microsoft.powershell.core/about/about_do
331+ [ about-while ] : /powershell/module/microsoft.powershell.core/about/about_while
332+ [ about-break ] : /powershell/module/microsoft.powershell.core/about/about_break
333+ [ about-continue ] : /powershell/module/microsoft.powershell.core/about/about_continue
334+ [ about-return ] : /powershell/module/microsoft.powershell.core/about/about_return
335+ [ the-powershell-return-keyword ] : https://mikefrobbins.com/2015/07/23/the-powershell-return-keyword/
0 commit comments