Control Flow
Master PowerShell control flow: if/elseif/else, switch statements, for loops, foreach, while loops, do-while, and do-until patterns.
📖 6 min read📅 2026-02-10Scripting
If / ElseIf / Else
The most basic control flow statement:
$score = 85
if ($score -ge 90) {
Write-Host "Grade: A" -ForegroundColor Green
}
elseif ($score -ge 80) {
Write-Host "Grade: B" -ForegroundColor Cyan
}
elseif ($score -ge 70) {
Write-Host "Grade: C" -ForegroundColor Yellow
}
else {
Write-Host "Grade: F" -ForegroundColor Red
}Single-Line If
# For simple conditions
if ($isAdmin) { Write-Host "Administrator" }
# Ternary (PowerShell 7+)
$message = $isAdmin ? "Admin" : "User"Nested If
$age = 25
$hasTicket = $true
if ($age -ge 18) {
if ($hasTicket) {
Write-Host "Welcome to the event!"
}
else {
Write-Host "Please purchase a ticket."
}
}
else {
Write-Host "Must be 18 or older."
}Switch Statement
More readable than multiple if/elseif blocks:
$day = (Get-Date).DayOfWeek
switch ($day) {
"Monday" { Write-Host "Start of the work week" }
"Friday" { Write-Host "TGIF!" }
"Saturday" { Write-Host "Weekend!" }
"Sunday" { Write-Host "Weekend!" }
default { Write-Host "Regular day" }
}Switch with Wildcards
$os = "Windows 11 Pro"
switch -Wildcard ($os) {
"Windows*" { Write-Host "Windows OS detected" }
"*Pro*" { Write-Host "Professional edition" }
"*Server*" { Write-Host "Server edition" }
}
# Note: Multiple matches fire! Both "Windows*" and "*Pro*" will matchSwitch with Regex
$input = "192.168.1.100"
switch -Regex ($input) {
"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$" {
Write-Host "Valid IP format: $input"
}
"^192\.168\." {
Write-Host "Private network (Class C)"
}
"^10\." {
Write-Host "Private network (Class A)"
}
}Switch on Arrays
$statusCodes = 200, 301, 404, 500, 200
switch ($statusCodes) {
200 { Write-Host "OK" }
301 { Write-Host "Redirect" }
404 { Write-Host "Not Found" }
500 { Write-Host "Server Error" }
}
# Evaluates each item in the array!For Loop
Classic counting loop:
# Count from 1 to 10
for ($i = 1; $i -le 10; $i++) {
Write-Host "Number: $i"
}
# Count by 2s
for ($i = 0; $i -le 20; $i += 2) {
Write-Host "Even: $i"
}
# Countdown
for ($i = 10; $i -ge 0; $i--) {
Write-Host "$i..."
}
Write-Host "Liftoff!"ForEach Loop
Iterate over collections:
# ForEach statement
$fruits = "Apple", "Banana", "Cherry"
foreach ($fruit in $fruits) {
Write-Host "I like $fruit"
}
# ForEach-Object cmdlet (pipeline)
$fruits | ForEach-Object { Write-Host "I like $_" }
# ForEach with index
$colors = "Red", "Green", "Blue"
for ($i = 0; $i -lt $colors.Count; $i++) {
Write-Host "$($i + 1). $($colors[$i])"
}
# Practical: Process files
foreach ($file in Get-ChildItem *.txt) {
$lines = (Get-Content $file).Count
Write-Host "$($file.Name): $lines lines"
}ForEach vs ForEach-Object
# ForEach statement - loads ALL items into memory first
foreach ($proc in Get-Process) {
# All processes loaded, then iterated
}
# ForEach-Object - processes one at a time (streaming)
Get-Process | ForEach-Object {
# Each process handled individually
}
# Use ForEach for small collections (faster)
# Use ForEach-Object for large data or pipeline integrationWhile Loop
Loop while a condition is true:
# Basic while
$count = 0
while ($count -lt 5) {
Write-Host "Count: $count"
$count++
}
# Wait for a process to start
while (-not (Get-Process -Name "notepad" -ErrorAction SilentlyContinue)) {
Write-Host "Waiting for Notepad..."
Start-Sleep -Seconds 2
}
Write-Host "Notepad is running!"
# Read user input until valid
$valid = $false
while (-not $valid) {
$input = Read-Host "Enter a number between 1-10"
if ($input -match "^\d+$" -and [int]$input -ge 1 -and [int]$input -le 10) {
$valid = $true
Write-Host "You entered: $input"
}
else {
Write-Host "Invalid input. Try again."
}
}Do-While and Do-Until
Execute at least once, then check condition:
# Do-While: Loop WHILE condition is true
$attempts = 0
do {
$attempts++
$guess = Read-Host "Guess the number (1-10)"
} while ($guess -ne "7" -and $attempts -lt 3)
# Do-Until: Loop UNTIL condition becomes true
$response = ""
do {
$response = Read-Host "Type 'quit' to exit"
} until ($response -eq "quit")Loop Control
Break — Exit the Loop
foreach ($i in 1..100) {
if ($i -eq 5) {
Write-Host "Found 5, breaking out!"
break
}
Write-Host $i
}
# Output: 1, 2, 3, 4, Found 5, breaking out!Continue — Skip to Next Iteration
foreach ($i in 1..10) {
if ($i % 2 -eq 0) {
continue # Skip even numbers
}
Write-Host "Odd: $i"
}
# Output: 1, 3, 5, 7, 9Labels — Control Nested Loops
:outer foreach ($i in 1..5) {
foreach ($j in 1..5) {
if ($j -eq 3) {
continue outer # Skip to next iteration of outer loop
}
Write-Host "i=$i, j=$j"
}
}Practical Examples
Example 1: Menu System
do {
Write-Host "`n=== System Menu ===" -ForegroundColor Cyan
Write-Host "1. Show running processes"
Write-Host "2. Show disk space"
Write-Host "3. Show network info"
Write-Host "4. Exit"
$choice = Read-Host "`nSelect an option"
switch ($choice) {
"1" {
Get-Process | Sort-Object CPU -Descending |
Select-Object -First 10 Name, CPU, WorkingSet |
Format-Table -AutoSize
}
"2" {
Get-PSDrive -PSProvider FileSystem |
Select-Object Name,
@{N="Used(GB)"; E={[math]::Round($_.Used/1GB,2)}},
@{N="Free(GB)"; E={[math]::Round($_.Free/1GB,2)}} |
Format-Table -AutoSize
}
"3" {
Get-NetIPAddress -AddressFamily IPv4 |
Where-Object IPAddress -ne "127.0.0.1" |
Select-Object InterfaceAlias, IPAddress |
Format-Table -AutoSize
}
"4" { Write-Host "Goodbye!" -ForegroundColor Green }
default { Write-Host "Invalid option" -ForegroundColor Red }
}
} while ($choice -ne "4")Example 2: Retry Logic
$maxRetries = 3
$retryCount = 0
$success = $false
while (-not $success -and $retryCount -lt $maxRetries) {
$retryCount++
Write-Host "Attempt $retryCount of $maxRetries..."
try {
# Simulate an operation that might fail
$result = Invoke-WebRequest "https://api.example.com/health" -TimeoutSec 5
if ($result.StatusCode -eq 200) {
$success = $true
Write-Host "Success!" -ForegroundColor Green
}
}
catch {
Write-Host "Failed. Retrying in 5 seconds..." -ForegroundColor Yellow
Start-Sleep -Seconds 5
}
}
if (-not $success) {
Write-Host "All attempts failed!" -ForegroundColor Red
}Exercises
- Write a script that prints the multiplication table (1-10) for a given number
- Create a number guessing game (random 1-100, give hints "higher/lower")
- Write a while loop that monitors a folder for new files every 10 seconds
- Use a switch statement to categorize HTTP status codes (1xx, 2xx, 3xx, 4xx, 5xx)
- Create a menu-driven script to manage files (create, list, delete, rename)
Next: Functions and Scripts — learn to write reusable code!