{"id":60832,"date":"2024-05-01T06:00:00","date_gmt":"2024-05-01T10:00:00","guid":{"rendered":"https:\/\/practical365.com\/?p=60832"},"modified":"2024-04-26T12:38:35","modified_gmt":"2024-04-26T16:38:35","slug":"practical-powershell-flow-control","status":"publish","type":"post","link":"https:\/\/practical365.com\/practical-powershell-flow-control\/","title":{"rendered":"Practical PowerShell: Flow Control"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#Looping\" >Looping<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#For-Loop\" >For-Loop<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#ForEach-Object_and_ForEach\" >ForEach-Object and ForEach<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#ForEach-Object_-Parallel\" >ForEach-Object -Parallel<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#While\" >While<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#Do-Until\" >Do-Until<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/#Loops_for_Iteration\" >Loops for Iteration<\/a><\/li><\/ul><\/nav><\/div>\n<div id=\"bsf_rt_marker\"><\/div>\n<p>&#8220;Control, Control, You Must Learn Control.&#8221; I rarely quote Yoda&#8217;s wisdom in articles, but this is an exception. After discussing advanced functions in <a href=\"https:\/\/practical365.com\/practical-powershell-functions-parameterization\/\" target=\"_blank\" rel=\"noreferrer noopener\">the second Practical PowerShell article<\/a>, the other important scripting skill to master is using the flow control cmdlets. These cmdlets are not just theoretical concepts; they are practical assets that can significantly enhance your PowerShell scripts.<\/p>\n\n\n\n<p>The concept of flow control is not new; it has been available in programming since the days of <a href=\"https:\/\/en.wikipedia.org\/wiki\/ENIAC#Programming\" target=\"_blank\" rel=\"noreferrer noopener\">ENIAC<\/a> (1945), where units of circuit boards with electric components were used to control the compute sequence.<\/p>\n\n\n\n<p>These concepts still exist today in most programming languages and shell environments. However, every language has its way of managing flow, and PowerShell is no exception. In this article, I discuss the code flow constructs available in PowerShell regarding looping and how to use them. In the next article, I will dive into branching. Meanwhile, I might pass an additional tip or two, so read on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-looping\"><span class=\"ez-toc-section\" id=\"Looping\"><\/span>Looping<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>You can use a loop to iterate through items of an array or a collection of objects, repeating code until a condition is satisfied or until the condition is no longer valid. You can iterate over items from arrays and collections until you have processed them all. In the examples for each loop option, I will use the example of calculating the average number of items in mailboxes.<\/p>\n\n\n\n<div class=\"q-blockads-inside-content q-blockads-entity-placement\" id=\"q-blockads-1479814394\"><div id=\"q-blockads-1013951058\"><p><a href=\"https:\/\/www.quest.com\/P365_On_Demand_Migration\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-62892\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-300x31.jpg\" alt=\"\" width=\"861\" height=\"89\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-300x31.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone-768x80.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/09\/1901-10-20-2025-Redone.jpg 860w\" sizes=\"auto, (max-width: 861px) 100vw, 861px\" \/><\/a><\/p>\n<\/div><\/div><h2 class=\"wp-block-heading\" id=\"h-for-loop\"><span class=\"ez-toc-section\" id=\"For-Loop\"><\/span>For-Loop<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>For is the loop type that continues to execute code until the condition is met. To define the conditions, you can create an initialization statement, a condition to stop the code from getting executed, and a step. The step statement is run on every iteration after executing the code and usually increments a counter, making the loop terminate when finished.<\/p>\n\n\n\n<p>An example of using For to go through an array of user objects:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$TotalItems= 0\n[array]$Users = Get-User -RecipientTypeDetails UserMailbox\nFor( $i=0; $i -lt $Users.count; $i++) {\n\u00a0\u00a0\u00a0 $TotalItems+= (Get-ExoMailboxStatistics -Identity $Users[ $i].externalDirectoryObjectId).ItemCount\n}\n$Avg= $TotalItems \/ $Users.Count\nWrite-Host ('Avg. Itemcount: {0}' -f $Avg)<\/pre>\n\n\n\n<p>Note that [array] casts the result of running the <em>Get-User<\/em> cmdlet to an array. The result of <em>Get-User<\/em> can be a collection of user objects or a single user object. Casting the result prevents having to add code to anticipate handling these differences. For example, when <em>Get-User<\/em> results in a single object, you can directly refer to its properties, e.g. $User.Identity. However, when multiple objects arw returned, this creates an array of all identities of the returned user objects. Read more on casting <a href=\"https:\/\/learn.microsoft.com\/powershell\/scripting\/lang-spec\/chapter-06?WT.mc_id=M365-MVP-5000284\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>In the example, I use the -format operator, or -f for short. This allows you to remove variable references from the string, improving readability. To use a formatted string, use numbered markers starting with {0} in the text, pass the corresponding variable or text after the format operator in the corresponding position, where the first passed item becomes {0}, and so on. You can do much more with the format operator, such as number justifying. Read more on the format operator <a href=\"https:\/\/learn.microsoft.com\/powershell\/module\/microsoft.powershell.core\/about\/about_operators?WT.mc_id=M365-MVP-5000284#format-operator--f\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-foreach-object-and-foreach\"><span class=\"ez-toc-section\" id=\"ForEach-Object_and_ForEach\"><\/span>ForEach-Object and ForEach<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>ForEach can refer to two different commands, which can be confusing. The first is ForEach as the alias for ForEach-Object (or %). It operates on pipeline input, going through the passed objects, which is usually an array or collection of objects. As ForEach-Object goes through every object, every object gets processed by a { code } script block, where the object itself can be referred to by the variable $_. You might already use ForEach-Object to process objects passed through a pipeline, especially when a cmdlet does not accept pipeline input or required parameters are not passed through the pipeline. For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$TotalItems= 0\n$Users= 0\nGet-User -RecipientTypeDetails UserMailbox | ForEach-Object {\n\u00a0\u00a0\u00a0 $TotalItems+= (Get-ExoMailboxStatistics -Identity $_.externalDirectoryObjectId).ItemCount\n\u00a0\u00a0\u00a0 $Users++\n}\n$Avg= $TotalItems \/ $Users\nWrite-Host ('Avg. Itemcount: {0}' -f $Avg)<\/pre>\n\n\n\n<p>Note that since we do not know the number of mailboxes upfront, we use an additional variable to keep track of the number to calculate the average.<\/p>\n\n\n\n<p>The other ForEach is similar to For, and can be used to iterate over an enumerable object. In other words, every element of an array or object collection. You can define the variable name to become the current object as ForEach goes through the array or collection, for example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$TotalItems= 0\n$Users= Get-User -RecipientTypeDetails UserMailbox\nForEach( $User in $Users) {\n\u00a0\u00a0\u00a0 $TotalItems+= (Get-ExoMailboxStatistics -Identity $User.externalDirectoryObjectId).ItemCount\n}\n$Avg= $TotalItems \/ $Users.Count\nWrite-Host ('Avg. Itemcount: {0}' -f $Avg)<\/pre>\n\n\n\n<p>Note that I did not cast $Users to an array, as ForEach will properly handle the results regardless of whether the collection is single or multiple objects.<\/p>\n\n\n\n<p>You can also use ForEach as a method of an array or collection, for example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$TotalItems= 0\n$Users= Get-User -RecipientTypeDetails UserMailbox $Users.ForEach{\n\u00a0\u00a0\u00a0 $TotalItems+= (Get-ExoMailboxStatistics -Identity $_.externalDirectoryObjectId).ItemCount\n}\n$Avg= $TotalItems \/ $Users.Count\nWrite-Host ('Avg. Itemcount: {0}' -f $Avg)<\/pre>\n\n\n\n<p>Apart from functional differences, the ForEach options can differ in performance. ForEach loads the complete collection prior to iteration, whereas ForEach-Object uses the pipeline to send objects through as they are fetched. The performance of the two commands depends on your collection and what processing takes place. If memory is a concern, ForEach-Object is the preferred choice. For readability, using the ForEach construct might be preferred.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-foreach-object-parallel\"><span class=\"ez-toc-section\" id=\"ForEach-Object_-Parallel\"><\/span>ForEach-Object -Parallel<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In PowerShell 7, the option exists to add a -Parallel switch to ForEach-Object, e.g. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Users | ForEach-Object -Parallel {\n\u00a0\u00a0\u00a0 Get-ExoMailboxStatistics -Identity $_.id\n}<\/pre>\n\n\n\n<p>While parallelization implies a performance benefit, remember you are using a shared service. Parallelization might result in the service throttling your code more quickly as it simultaneously fires requests at the Graph or one of the other workloads. In addition, the default for running in parallel is 5 (configurable using the ThrottleLimit parameter). Each parallel running piece of code runs in its own runspace, which is a separate context containing all of the functions and loaded modules of the caller. Just be advised that variables from the caller need to be referenced explicitly by prefixing them using $using, e.g.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Props= 'TotalItemSize', 'TotalDeletedItemSize'\n$Users | ForEach-Object -Parallel {\n\u00a0\u00a0\u00a0 Get-ExoMailboxStatistics -Identity $_.id -Properties $using:Props\n}<\/pre>\n\n\n\n<p>A certain overhead is involved in creating and disposing of the runspaces running this code, which might harm overall performance if your code is more processing-oriented. If your code is talking to Microsoft 365, the overhead might be negligible compared to the additional overhead from just interacting with the service.<\/p>\n\n\n\n<p>Finally, objects sent through the pipeline are normally processed in sequential order. When using -Parallel, the order is undetermined. So, using ForEach-Object with the Parallel switch might bring some benefits, but testing is advised as your mileage may vary.<\/p>\n\n\n\n<div class=\"q-blockads-content q-blockads-entity-placement\" id=\"q-blockads-2840692134\"><div id=\"q-blockads-122400996\"><p><a href=\"https:\/\/www.quest.com\/Security_Guardian_P365\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-62893\" src=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-300x31.jpg\" alt=\"\" width=\"861\" height=\"89\" srcset=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-300x31.jpg 300w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone-768x80.jpg 768w, https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1902-10-20-2025-Redone.jpg 860w\" sizes=\"auto, (max-width: 861px) 100vw, 861px\" \/><\/a><\/p>\n<\/div><\/div><h2 class=\"wp-block-heading\" id=\"h-while\"><span class=\"ez-toc-section\" id=\"While\"><\/span>While<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A While loop is a conditional loop that processes the code when the condition is met and keeps repeating the code until the condition is no longer met. Depending on the condition, a while loop does not necessarily execute the code.<\/p>\n\n\n\n<p>Practical 365 recently showed an example of using While in this <a href=\"https:\/\/practical365.com\/pagination-graph-sdk\/\" target=\"_blank\" rel=\"noreferrer noopener\">example<\/a> of how to fetch paginated results from Graph:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Teams.Value.ForEach( {\n\u00a0\u00a0 $TeamsHash.Add($_.Id, $_.DisplayName) } )\n\u00a0\u00a0 $NextLink = $Teams.'@Odata.NextLink'\n\u00a0\u00a0\u00a0\u00a0\u00a0 While ($NextLink -ne $Null) {\n\u00a0\u00a0\u00a0\u00a0\u00a0 $Teams = Invoke-WebRequest -Method GET -Uri $NextLink -ContentType $ContentType -Headers $Headers | ConvertFrom-Json\n\u00a0\u00a0\u00a0\u00a0\u00a0 $Teams.Value.ForEach( {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $TeamsHash.Add($_.Id, $_.DisplayName) } )\n\u00a0\u00a0 $NextLink = $Teams.'@odata.NextLink'\n}<\/pre>\n\n\n\n<p>Here, the value of the NextLink value returned by a Graph API request is retrieved, and if it contains a value (not null), the code will be iterated until no NextLink is remaining. A common pattern for While, as also visible in the example, is that the evaluation related to the condition stated before the while (to trigger the first run of code) and at the bottom of the loop script block, in this case <em>$NextLink = $Teams.&#8217;@odata.NextLink&#8217;<\/em>.<\/p>\n\n\n\n<p>A word of warning. When working with loops such as While, ensure the condition is matched at some point to avoid infinite loops. The same applies to Do-While and Do-Until. For example, in the following code the incrementing of the index i is accidentally omitted, resulting in the loop never to terminate:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[array]$Users = Get-User -RecipientTypeDetails UserMailbox\n$i=0\nWhile( $i -lt $Users.count) {\n\u00a0\u00a0\u00a0 Get-ExoMailboxStatistics -Identity $Users[ $i].externalDirectoryObjectId).ItemCount\n}<\/pre>\n\n\n\n<p>A Do-While is a conditional loop that runs code at least once, as opposed to While, and will continue repeating code as long as the condition is met. It is used when you are certain the code can execute. For this example, let us assume you create a guest user using the PowerShell Graph SDK and need to show a visual clue that the script is waiting for the provisioning to finish before it can modify certain Exchange Online-related properties, e.g.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$Alias= 'philip_contoso.com#ext'\n$UPN= '{0}@contoso.onmicrosoft.com' -f $Alias\n$Props= @{\n\u00a0 DisplayName= 'Philip'\n\u00a0 Mail= 'philip@contoso.com'\n\u00a0 MailNickname= $Alias\n\u00a0 UserPrincipalName= $UPN\n\u00a0 UserType= 'Guest'\n}\n$Account = New-MgUser @Props\n\nDo {\n\u00a0 Write-Host ('Waiting for Guest provisioning ..')\n\u00a0 Start-Sleep 60\n} While ( $null -eq (Get-MailUser -Identity $UPN -ErrorAction SilentlyContinue))\n\nSet-MailUser -Identity $UPN -HiddenFromAddressListEnabled:$false<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-do-until\"><span class=\"ez-toc-section\" id=\"Do-Until\"><\/span>Do-Until<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A Do-Until is a conditional loop that will loop and run code at least once and will continue repeating it until the condition is met. It differs from Do-While in that Do-While loops the code as long as the condition is met. Both can be refactored as the other, making it in my opinion a matter of trying to avoid double negatives and improved readability.<\/p>\n\n\n\n<p>An example of a double negative could be something such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Do { .. } Until ( -not ( $number -lt 10))<\/pre>\n\n\n\n<p>This will loop the code until the number is not less than 10.<\/p>\n\n\n\n<p>This could be rewritten as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Do { .. } Until ( $number -ge 10)<\/pre>\n\n\n\n<p>or<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Do { .. } While ( $number -lt 10)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-loops-for-iteration\"><span class=\"ez-toc-section\" id=\"Loops_for_Iteration\"><\/span>Loops for Iteration<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Talking about flow control touches on elementary programming. Looping is part of this. Knowing about these constructs and when which programming is appropriate helps you iterate through user or mailbox objects in a way that is efficient while retaining readability.<\/p>\n\n\n\n<p>Feel free to reach out in the comments if you have questions or comments. If not, until the next article, where I will talk about another type of construct in flow control, which is branching.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.<\/p>\n","protected":false},"author":152,"featured_media":60837,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[9055],"tags":[11121,238],"class_list":["post-60832","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-flow-control","tag-powershell","entry","has-media"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.2 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Practical PowerShell: Flow Control | Practical365<\/title>\n<meta name=\"description\" content=\"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/practical365.com\/practical-powershell-flow-control\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Practical PowerShell: Flow Control\" \/>\n<meta property=\"og:description\" content=\"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/practical365.com\/practical-powershell-flow-control\/\" \/>\n<meta property=\"og:site_name\" content=\"Practical 365\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Practical365\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-01T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Michel De Rooij\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mderooij\" \/>\n<meta name=\"twitter:site\" content=\"@Practical365\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michel De Rooij\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/\"},\"author\":{\"name\":\"Michel De Rooij\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/person\\\/5c301450490c89fc62c2f1da69eac5fd\"},\"headline\":\"Practical PowerShell: Flow Control\",\"datePublished\":\"2024-05-01T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/\"},\"wordCount\":1408,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/1169-01-01-2024-Flow-Control-LOW.jpg\",\"keywords\":[\"Flow Control\",\"PowerShell\"],\"articleSection\":[\"PowerShell\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/\",\"url\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/\",\"name\":\"Practical PowerShell: Flow Control | Practical365\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/1169-01-01-2024-Flow-Control-LOW.jpg\",\"datePublished\":\"2024-05-01T10:00:00+00:00\",\"description\":\"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#primaryimage\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/1169-01-01-2024-Flow-Control-LOW.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/1169-01-01-2024-Flow-Control-LOW.jpg\",\"width\":1100,\"height\":500},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/practical365.com\\\/practical-powershell-flow-control\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/practical365.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/practical365.com\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Practical PowerShell: Flow Control\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#website\",\"url\":\"https:\\\/\\\/practical365.com\\\/\",\"name\":\"Practical 365\",\"description\":\"Practical Office 365 News, Tips, and Tutorials\",\"publisher\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/practical365.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#organization\",\"name\":\"Practical 365\",\"url\":\"https:\\\/\\\/practical365.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/Logo-P365-stacked.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/Logo-P365-stacked.jpg\",\"width\":1176,\"height\":696,\"caption\":\"Practical 365\"},\"image\":{\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Practical365\",\"https:\\\/\\\/x.com\\\/Practical365\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/practical365-com\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/practical365.com\\\/#\\\/schema\\\/person\\\/5c301450490c89fc62c2f1da69eac5fd\",\"name\":\"Michel De Rooij\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/10\\\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg\",\"url\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/10\\\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/practical365.com\\\/wp-content\\\/uploads\\\/2024\\\/10\\\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg\",\"caption\":\"Michel De Rooij\"},\"description\":\"Michel de Rooij, with over 25 years of mixed consulting and automation experience with Exchange and related technologies, is a consultant for Rapid Circle. He assists organizations in their journey to and using Microsoft 365, primarily focusing on Exchange and associated technologies and automating processes using PowerShell or Graph. Michel's authorship of several Exchange books and role in the Office 365 for IT Pros author team are a testament to his knowledge. Besides writing for Practical365.com, he maintains a blog on eightwone.com with supporting scripts on GitHub. Michel has been a Microsoft MVP since 2013.\",\"sameAs\":[\"https:\\\/\\\/eightwone.com\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/michelderooij\\\/\",\"https:\\\/\\\/x.com\\\/mderooij\"],\"url\":\"https:\\\/\\\/practical365.com\\\/author\\\/michelderooij\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Practical PowerShell: Flow Control | Practical365","description":"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/practical365.com\/practical-powershell-flow-control\/","og_locale":"en_US","og_type":"article","og_title":"Practical PowerShell: Flow Control","og_description":"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.","og_url":"https:\/\/practical365.com\/practical-powershell-flow-control\/","og_site_name":"Practical 365","article_publisher":"https:\/\/www.facebook.com\/Practical365","article_published_time":"2024-05-01T10:00:00+00:00","og_image":[{"width":1100,"height":500,"url":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg","type":"image\/jpeg"}],"author":"Michel De Rooij","twitter_card":"summary_large_image","twitter_creator":"@mderooij","twitter_site":"@Practical365","twitter_misc":{"Written by":"Michel De Rooij","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#article","isPartOf":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/"},"author":{"name":"Michel De Rooij","@id":"https:\/\/practical365.com\/#\/schema\/person\/5c301450490c89fc62c2f1da69eac5fd"},"headline":"Practical PowerShell: Flow Control","datePublished":"2024-05-01T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/"},"wordCount":1408,"commentCount":0,"publisher":{"@id":"https:\/\/practical365.com\/#organization"},"image":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#primaryimage"},"thumbnailUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg","keywords":["Flow Control","PowerShell"],"articleSection":["PowerShell"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/practical365.com\/practical-powershell-flow-control\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/","url":"https:\/\/practical365.com\/practical-powershell-flow-control\/","name":"Practical PowerShell: Flow Control | Practical365","isPartOf":{"@id":"https:\/\/practical365.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#primaryimage"},"image":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#primaryimage"},"thumbnailUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg","datePublished":"2024-05-01T10:00:00+00:00","description":"In this edition of Practical PowerShell, Michel De Rooij discusses the code flow constructs available in PowerShell regarding looping and how to use them.","breadcrumb":{"@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/practical365.com\/practical-powershell-flow-control\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#primaryimage","url":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/04\/1169-01-01-2024-Flow-Control-LOW.jpg","width":1100,"height":500},{"@type":"BreadcrumbList","@id":"https:\/\/practical365.com\/practical-powershell-flow-control\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/practical365.com\/"},{"@type":"ListItem","position":2,"name":"PowerShell","item":"https:\/\/practical365.com\/powershell\/"},{"@type":"ListItem","position":3,"name":"Practical PowerShell: Flow Control"}]},{"@type":"WebSite","@id":"https:\/\/practical365.com\/#website","url":"https:\/\/practical365.com\/","name":"Practical 365","description":"Practical Office 365 News, Tips, and Tutorials","publisher":{"@id":"https:\/\/practical365.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/practical365.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/practical365.com\/#organization","name":"Practical 365","url":"https:\/\/practical365.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/#\/schema\/logo\/image\/","url":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/Logo-P365-stacked.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2022\/06\/Logo-P365-stacked.jpg","width":1176,"height":696,"caption":"Practical 365"},"image":{"@id":"https:\/\/practical365.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Practical365","https:\/\/x.com\/Practical365","https:\/\/www.linkedin.com\/company\/practical365-com"]},{"@type":"Person","@id":"https:\/\/practical365.com\/#\/schema\/person\/5c301450490c89fc62c2f1da69eac5fd","name":"Michel De Rooij","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/10\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg","url":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/10\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg","contentUrl":"https:\/\/practical365.com\/wp-content\/uploads\/2024\/10\/cropped-5E56A01C-A1C9-4D0A-BE6E-3B478879425E-square-96x96.jpg","caption":"Michel De Rooij"},"description":"Michel de Rooij, with over 25 years of mixed consulting and automation experience with Exchange and related technologies, is a consultant for Rapid Circle. He assists organizations in their journey to and using Microsoft 365, primarily focusing on Exchange and associated technologies and automating processes using PowerShell or Graph. Michel's authorship of several Exchange books and role in the Office 365 for IT Pros author team are a testament to his knowledge. Besides writing for Practical365.com, he maintains a blog on eightwone.com with supporting scripts on GitHub. Michel has been a Microsoft MVP since 2013.","sameAs":["https:\/\/eightwone.com","https:\/\/www.linkedin.com\/in\/michelderooij\/","https:\/\/x.com\/mderooij"],"url":"https:\/\/practical365.com\/author\/michelderooij\/"}]}},"_links":{"self":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts\/60832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/users\/152"}],"replies":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/comments?post=60832"}],"version-history":[{"count":0,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/posts\/60832\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/media\/60837"}],"wp:attachment":[{"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/media?parent=60832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/categories?post=60832"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/practical365.com\/wp-json\/wp\/v2\/tags?post=60832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}