Switch Statements
Note
Learn how to efficiently handle multiple conditions using switch statements instead of long if/elseif chains.
Overview
A switch statement lets you check one value against multiple possible matches. Instead of writing many if/elseif statements, you use switch to make your code cleaner and easier to read. Think of it like a multiple-choice question where you execute different code based on which answer matches.
Basic Syntax
switch (value-to-test) {
"match1" { # Code if value equals "match1" }
"match2" { # Code if value equals "match2" }
"match3" { # Code if value equals "match3" }
default { # Code if no matches found }
}
Key Points
- Tests one value against multiple possible matches
- Cleaner than long if/elseif chains
- Supports wildcards, regex, and conditions
- Can match multiple cases (doesn't auto-break like other languages)
- Case-insensitive by default (use
-casesensitivefor exact matching)
Simple Switch Statements
Basic Value Matching
$dayOfWeek = (Get-Date).DayOfWeek
switch ($dayOfWeek) {
"Monday" { Write-Output "Start of the work week" }
"Tuesday" { Write-Output "Second day" }
"Wednesday" { Write-Output "Midweek" }
"Thursday" { Write-Output "Almost Friday" }
"Friday" { Write-Output "TGIF!" }
"Saturday" { Write-Output "Weekend!" }
"Sunday" { Write-Output "Weekend!" }
}
Using Default
$status = "Unknown"
switch ($status) {
"Active" { Write-Output "User is active" }
"Inactive" { Write-Output "User is inactive" }
"Pending" { Write-Output "User is pending approval" }
default { Write-Output "Status not recognized: $status" }
}
Output:
Common Use Cases
Use Case 1: Menu Systems
What it does: Create interactive menus
Write-Output "`n===== Main Menu ====="
Write-Output "1. View Files"
Write-Output "2. Create File"
Write-Output "3. Delete File"
Write-Output "4. Exit"
$choice = Read-Host "`nEnter your choice"
switch ($choice) {
"1" {
Write-Output "Viewing files..."
Get-ChildItem
}
"2" {
$filename = Read-Host "Enter filename"
New-Item -Path $filename -ItemType File
Write-Output "File created: $filename"
}
"3" {
$filename = Read-Host "Enter filename to delete"
Remove-Item -Path $filename
Write-Output "File deleted: $filename"
}
"4" {
Write-Output "Exiting..."
exit
}
default {
Write-Output "Invalid choice. Please try again."
}
}
Use Case 2: File Extension Handling
What it does: Process files differently based on extension
$file = Get-Item "C:\Temp\document.pdf"
switch ($file.Extension) {
".txt" {
Write-Output "Text file - displaying first 10 lines..."
Get-Content -Path $file.FullName -TotalCount 10
}
".csv" {
Write-Output "CSV file - importing data..."
$data = Import-Csv -Path $file.FullName
Write-Output "Rows: $($data.Count)"
}
{$_ -in @(".jpg", ".png", ".gif")} {
Write-Output "Image file - opening in viewer..."
Invoke-Item -Path $file.FullName
}
".pdf" {
Write-Output "PDF file"
Write-Output "Size: $([math]::Round($file.Length/1MB, 2)) MB"
}
default {
Write-Output "Unknown file type: $($file.Extension)"
}
}
Use Case 3: Error Code Handling
What it does: Take different actions based on error codes
$exitCode = 1
switch ($exitCode) {
0 {
Write-Output "Success"
# Continue processing
}
1 {
Write-Warning "General error occurred"
# Log and retry
}
2 {
Write-Error "File not found"
# Create file and retry
}
{$_ -in 3..10} {
Write-Warning "Configuration error (code: $_)"
# Reset config
}
default {
Write-Error "Unknown error code: $exitCode"
# Alert admin
}
}
Advanced Switch Features
Wildcard Matching
$filename = "report_2025_november.txt"
switch -Wildcard ($filename) {
"*.txt" {
Write-Output "Text file"
}
"report_*" {
Write-Output "This is a report file"
}
"*2025*" {
Write-Output "File from 2025"
}
}
Output:
Note: Unlike most languages, PowerShell switch doesn't automatically "break" - it checks ALL cases that match!
Regex Matching
$input = "Server01"
switch -Regex ($input) {
"^Server\d+$" {
Write-Output "Valid server name format"
}
"^\d+$" {
Write-Output "Numeric value"
}
"^[A-Z]" {
Write-Output "Starts with uppercase letter"
}
}
Output:
Case-Sensitive Matching
$value = "PowerShell"
# Default: case-insensitive
switch ($value) {
"powershell" { Write-Output "Matched (case-insensitive)" }
}
# Output: Matched (case-insensitive)
# Case-sensitive
switch -CaseSensitive ($value) {
"powershell" { Write-Output "Matched" }
"PowerShell" { Write-Output "Exact match!" }
}
# Output: Exact match!
Condition-Based Matching
$number = 42
switch ($number) {
{$_ -lt 0} { Write-Output "Negative number" }
{$_ -eq 0} { Write-Output "Zero" }
{$_ -le 10} { Write-Output "Between 1 and 10" }
{$_ -le 50} { Write-Output "Between 11 and 50" }
{$_ -le 100} { Write-Output "Between 51 and 100" }
{$_ % 2 -eq 0} { Write-Output "Even number" }
default { Write-Output "Greater than 100" }
}
Output:
Processing Arrays with Switch
$services = "Spooler", "W32Time", "WinRM", "UnknownService"
switch ($services) {
"Spooler" {
Write-Output "Print Spooler service"
}
"W32Time" {
Write-Output "Windows Time service"
}
"WinRM" {
Write-Output "Windows Remote Management"
}
default {
Write-Output "Unknown service: $_"
}
}
Output:
Print Spooler service
Windows Time service
Windows Remote Management
Unknown service: UnknownService
Controlling Switch Flow
Break (Stop Processing)
$value = "test"
switch -Wildcard ($value) {
"t*" {
Write-Output "Starts with 't'"
break # Stop checking other cases
}
"*e*" {
Write-Output "Contains 'e'" # Won't run due to break
}
"test" {
Write-Output "Exact match" # Won't run due to break
}
}
Output:
Continue (Skip to Next Item)
$numbers = 1, 2, 3, 4, 5
switch ($numbers) {
{$_ % 2 -eq 0} {
Write-Output "$_ is even"
continue # Skip to next number
}
{$_ -gt 3} {
Write-Output "$_ is greater than 3"
}
default {
Write-Output "Processing $_"
}
}
Real-World Examples
Example: Service Status Reporter
Scenario: Generate different reports based on service status
function Get-ServiceReport {
param([string]$ServiceName)
$service = Get-Service -Name $ServiceName
switch ($service.Status) {
"Running" {
[PSCustomObject]@{
Service = $ServiceName
Status = "Running"
Action = "None required"
Priority = "Low"
}
}
"Stopped" {
# Check if it should be running
if ($service.StartType -eq "Automatic") {
[PSCustomObject]@{
Service = $ServiceName
Status = "Stopped"
Action = "Start service immediately"
Priority = "High"
}
} else {
[PSCustomObject]@{
Service = $ServiceName
Status = "Stopped"
Action = "Manual start only"
Priority = "Low"
}
}
}
{$_ -in "Paused", "StartPending", "StopPending"} {
[PSCustomObject]@{
Service = $ServiceName
Status = $service.Status
Action = "Monitor for state change"
Priority = "Medium"
}
}
default {
[PSCustomObject]@{
Service = $ServiceName
Status = $service.Status
Action = "Unknown status - investigate"
Priority = "High"
}
}
}
}
# Usage
Get-ServiceReport -ServiceName "Spooler"
Example: Log Level Handler
Scenario: Route log messages to different outputs based on severity
function Write-Log {
param(
[string]$Message,
[ValidateSet("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "[$timestamp] [$Level] $Message"
switch ($Level) {
"DEBUG" {
Write-Verbose $logEntry
}
"INFO" {
Write-Output $logEntry
Add-Content -Path "C:\Logs\info.log" -Value $logEntry
}
"WARNING" {
Write-Warning $Message
Add-Content -Path "C:\Logs\warning.log" -Value $logEntry
}
{$_ -in "ERROR", "CRITICAL"} {
Write-Error $Message
Add-Content -Path "C:\Logs\error.log" -Value $logEntry
if ($Level -eq "CRITICAL") {
# Send email alert for critical errors
Write-Output "ALERT: Critical error logged!"
}
}
}
}
# Usage
Write-Log "Application started" -Level INFO
Write-Log "Low disk space" -Level WARNING
Write-Log "Database connection failed" -Level CRITICAL
Example: HTTP Status Code Handler
Scenario: Handle different HTTP response codes appropriately
function Handle-HttpResponse {
param([int]$StatusCode)
switch ($StatusCode) {
{$_ -in 200..299} {
Write-Output "Success (Code: $_)"
return $true
}
{$_ -in 300..399} {
Write-Warning "Redirect (Code: $_)"
return $true
}
401 {
Write-Error "Unauthorized - Check credentials"
return $false
}
403 {
Write-Error "Forbidden - Insufficient permissions"
return $false
}
404 {
Write-Error "Not Found - Check URL"
return $false
}
{$_ -in 400..499} {
Write-Error "Client Error (Code: $_)"
return $false
}
{$_ -in 500..599} {
Write-Error "Server Error (Code: $_)"
return $false
}
default {
Write-Warning "Unknown status code: $_"
return $false
}
}
}
# Usage
$statusCode = 404
$success = Handle-HttpResponse -StatusCode $statusCode
Switch vs If/ElseIf
When to Use Switch
# Use switch when checking ONE value against MANY possibilities
switch ($fileExtension) {
".txt" { "Text file" }
".csv" { "CSV file" }
".json" { "JSON file" }
".xml" { "XML file" }
".log" { "Log file" }
default { "Unknown" }
}
When to Use If/ElseIf
# Use if/elseif when checking DIFFERENT conditions
if ($fileSize -gt 100MB) {
"Large file"
} elseif ($fileAge -gt 30) {
"Old file"
} elseif ($fileName -like "*.tmp") {
"Temporary file"
}
Tips & Tricks
Multiple Matches Execute by Default
# All matching cases run!
switch -Wildcard ("test.txt") {
"*.txt" { Write-Output "Text file" }
"test*" { Write-Output "Test file" }
"*.*" { Write-Output "Has extension" }
}
# Output: All three messages
# Use 'break' to stop after first match
switch -Wildcard ("test.txt") {
"*.txt" { Write-Output "Text file"; break }
"test*" { Write-Output "Test file" }
"*.*" { Write-Output "Has extension" }
}
# Output: Only "Text file"
Use Conditions for Range Checking
Process Multiple Values at Once
Case Insensitive by Default
# These both match
switch ("PowerShell") {
"powershell" { "Matched!" } # Matches!
"POWERSHELL" { "Also matches!" } # Also matches!
}
# Use -CaseSensitive if you need exact matching
switch -CaseSensitive ("PowerShell") {
"powershell" { "Won't match" }
"PowerShell" { "Exact match!" } # Only this matches
}
Default Runs When No Matches
Related Topics
- If Statements & Conditional Logic - Alternative for complex conditions
- Loops - Combining switch with loops
- Functions - Using switch in functions
- Error Handling - Handling errors in switch statements