Welcome to PowerShell
A modern, object-oriented command-line shell and scripting language
PowerShell is Microsoft's task automation framework built on .NET. Unlike traditional shells that pass text between commands, PowerShell works with objects — structured data with properties and methods. This makes it incredibly powerful for system administration, automation, and cybersecurity tasks.
Why PowerShell Matters
PowerShell is the backbone of Windows administration and is increasingly important in cross-platform environments (it runs on Linux and macOS too). It's essential for anyone working in IT, DevOps, or cybersecurity.
PowerShell commands output .NET objects, not plain text. This means you can access properties and methods on the output of any command — a paradigm shift from bash/cmd.
Versions at a Glance
| Version | Name | Platform | Notes |
|---|---|---|---|
| 1.0 – 5.1 | Windows PowerShell | Windows only | Ships with Windows, built on .NET Framework |
| 6.0+ | PowerShell Core | Cross-platform | Open-source, built on .NET Core |
| 7.x | PowerShell 7 | Cross-platform | Current recommended version |
Your First Command
Open a PowerShell terminal and type:
Write-Host "Hello, PowerShell!" -ForegroundColor Cyan
This prints colored text to the console. Write-Host is a cmdlet, "Hello, PowerShell!" is a positional argument, and -ForegroundColor is a named parameter.
What cmdlet would you use to display the current date and time? Type it below.
Cmdlets & Syntax
The building blocks of PowerShell — Verb-Noun commands with powerful parameters
The Verb-Noun Convention
Every cmdlet follows the Verb-Noun pattern. The verb describes the action, and the noun describes what it acts on. This makes commands discoverable and predictable.
| Verb | Purpose | Examples |
|---|---|---|
Get | Retrieve data | Get-Process, Get-Service, Get-ChildItem |
Set | Modify data | Set-Location, Set-Variable, Set-Content |
New | Create something | New-Item, New-Object, New-Variable |
Remove | Delete something | Remove-Item, Remove-Variable |
Start/Stop | Control execution | Start-Process, Stop-Service |
Import/Export | Data transfer | Import-Csv, Export-Clixml |
Invoke | Run an action | Invoke-Command, Invoke-WebRequest |
Discovering Commands
# Find all commands with "Process" in the name Get-Command -Name *Process* # List all verbs Get-Verb # Get detailed help on a cmdlet Get-Help Get-Process -Detailed # See examples for a cmdlet Get-Help Get-Service -Examples
Get-Help, Get-Command, and Get-Member are the "Big Three" discovery cmdlets. Master these and you can figure out almost anything in PowerShell.
Parameters
Cmdlets accept named parameters (prefixed with -), positional parameters, and switch parameters (booleans).
# Named parameter Get-Process -Name "notepad" # Positional parameter (same as above) Get-Process "notepad" # Switch parameter (boolean flag) Get-ChildItem -Recurse # Multiple parameters Get-EventLog -LogName "Application" -Newest 10
Aliases
PowerShell includes aliases for convenience. Many match familiar commands from cmd.exe or bash:
| Alias | Full Cmdlet | Origin |
|---|---|---|
ls, dir | Get-ChildItem | bash / cmd |
cd | Set-Location | Universal |
cp, copy | Copy-Item | bash / cmd |
mv, move | Move-Item | bash / cmd |
rm, del | Remove-Item | bash / cmd |
cat, type | Get-Content | bash / cmd |
cls, clear | Clear-Host | cmd / bash |
While aliases make typing faster, always use full cmdlet names in scripts for readability and maintainability.
What command would you use to get a list of all running services on the system?
The Pipeline
Chain commands together to build powerful one-liners
How the Pipeline Works
The pipe operator | passes the output objects of one command as input to the next. Because PowerShell works with objects (not text), you can filter, sort, and transform data seamlessly.
# Get processes → sort by memory → take top 5 Get-Process | Sort-Object -Property WorkingSet64 -Descending | Select-Object -First 5 # Get services → filter running ones → format as table Get-Service | Where-Object { $_.Status -eq "Running" } | Format-Table Name, Status # Get files → filter by extension → measure total size Get-ChildItem -Path "C:\Logs" -Filter "*.log" | Measure-Object -Property Length -Sum
Key Pipeline Cmdlets
| Cmdlet | Purpose | Example |
|---|---|---|
Where-Object | Filter objects | ... | Where-Object { $_.CPU -gt 10 } |
Select-Object | Choose properties or count | ... | Select-Object Name, Id -First 3 |
Sort-Object | Sort results | ... | Sort-Object Length -Descending |
ForEach-Object | Iterate and transform | ... | ForEach-Object { $_.Name.ToUpper() } |
Measure-Object | Count, sum, average | ... | Measure-Object -Sum |
Group-Object | Group by a property | ... | Group-Object Extension |
Format-Table | Display as table | ... | Format-Table -AutoSize |
Export-Csv | Save to CSV file | ... | Export-Csv output.csv |
$_ (or $PSItem) represents the current object in the pipeline. You'll use it constantly inside Where-Object and ForEach-Object script blocks { }.
Write a pipeline that gets all processes and filters only those where the process name is "svchost". Use Where-Object with $_.Name.
Variables & Types
Store data in variables — PowerShell is dynamically typed but type-aware
Creating Variables
Variables in PowerShell start with $. They're dynamically typed, meaning the type is inferred from the assigned value.
# String $name = "Alice" # Integer $age = 30 # Boolean $isAdmin = $true # Array $colors = "red", "green", "blue" $colors = @("red", "green", "blue") # explicit array syntax # Hashtable (dictionary) $user = @{ Name = "Alice" Age = 30 Admin = $true } # Access hashtable values $user.Name # "Alice" $user["Age"] # 30 # Check a variable's type $name.GetType().Name # String
Type Casting
You can enforce types by placing the type in brackets before the variable or value:
[int]$count = "42" # Converts string to int [string]$text = 100 # Converts int to string [datetime]$date = "2025-01-15" # Parses a date [array]$list = "single" # Forces single item into array
Special Variables
| Variable | Description |
|---|---|
$_ / $PSItem | Current pipeline object |
$null | Null value |
$true / $false | Boolean values |
$PWD | Current working directory |
$HOME | User's home directory |
$Error | Array of recent errors |
$PSVersionTable | PowerShell version info |
$env:PATH | Environment variables |
Create a variable called $greeting and assign it the string "Hello World". Type the full assignment statement.
Operators
Comparison, logical, and special operators that power your conditions
Comparison Operators
PowerShell uses text-based operators instead of symbols like > or < (which are reserved for redirection).
| Operator | Meaning | Example |
|---|---|---|
-eq | Equal to | 5 -eq 5 → True |
-ne | Not equal | 5 -ne 3 → True |
-gt | Greater than | 10 -gt 5 → True |
-lt | Less than | 3 -lt 7 → True |
-ge | Greater or equal | 5 -ge 5 → True |
-le | Less or equal | 4 -le 5 → True |
-like | Wildcard match | "hello" -like "hel*" → True |
-match | Regex match | "abc123" -match "\d+" → True |
-contains | Collection contains | @(1,2,3) -contains 2 → True |
-in | Value in collection | 2 -in @(1,2,3) → True |
By default, string comparisons are case-insensitive. Prefix with c for case-sensitive: -ceq, -clike, -cmatch.
Logical Operators
# AND — both must be true (5 -gt 3) -and (10 -lt 20) # True # OR — at least one must be true (5 -gt 10) -or (3 -eq 3) # True # NOT — negation -not (5 -eq 3) # True !(5 -eq 3) # True (shorthand)
Which PowerShell operator checks if a string matches a wildcard pattern? (e.g., checking if a filename matches *.txt)
Control Flow
Conditionals, loops, and flow control to build logic into your scripts
If / ElseIf / Else
$score = 85 if ($score -ge 90) { Write-Host "Grade: A" } elseif ($score -ge 80) { Write-Host "Grade: B" } elseif ($score -ge 70) { Write-Host "Grade: C" } else { Write-Host "Grade: F" }
Switch Statement
$day = (Get-Date).DayOfWeek switch ($day) { "Monday" { Write-Host "Start of the week" } "Friday" { Write-Host "Almost weekend!" } "Saturday" { Write-Host "Weekend!" } "Sunday" { Write-Host "Weekend!" } default { Write-Host "Midweek grind" } }
Loops
# For loop for ($i = 0; $i -lt 5; $i++) { Write-Host "Iteration: $i" } # ForEach loop $fruits = "apple", "banana", "cherry" foreach ($fruit in $fruits) { Write-Host "I like $fruit" } # While loop $count = 0 while ($count -lt 3) { Write-Host "Count: $count" $count++ } # Do-While (runs at least once) do { $input = Read-Host "Enter 'quit' to exit" } while ($input -ne "quit") # Pipeline ForEach 1..5 | ForEach-Object { $_ * 2 } # Output: 2, 4, 6, 8, 10
Write a foreach loop that iterates over $items and uses Write-Host to print each item. Use $item as the loop variable.
Functions
Encapsulate reusable logic with parameters and return values
Basic Function
function Get-Greeting { param( [string]$Name = "World" ) return "Hello, $Name!" } Get-Greeting # "Hello, World!" Get-Greeting -Name "Alice" # "Hello, Alice!"
Advanced Functions
Advanced functions add features like mandatory parameters, validation, pipeline input, and verbose/debug support.
function Get-DiskSpace { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$ComputerName, [ValidateSet("GB","MB","TB")] [string]$Unit = "GB" ) begin { Write-Verbose "Starting disk check..." } process { $divisor = switch ($Unit) { "TB" { 1TB }; "GB" { 1GB }; "MB" { 1MB } } Get-CimInstance Win32_LogicalDisk -ComputerName $ComputerName | Select-Object DeviceID, @{N="FreeSpace($Unit)"; E={[math]::Round($_.FreeSpace / $divisor, 2)}} } end { Write-Verbose "Done." } }
These blocks handle pipeline input. begin runs once first, process runs for each piped object, and end runs once after all input. Use them when your function accepts pipeline input.
What keyword starts a function definition in PowerShell?
File System Operations
Navigate, create, read, and manipulate files and directories
Navigation & Listing
# Current location Get-Location # alias: pwd # Change directory Set-Location "C:\Users" # alias: cd # List files and folders Get-ChildItem # alias: ls, dir Get-ChildItem -Recurse -Filter "*.log" # List only directories Get-ChildItem -Directory # List hidden files too Get-ChildItem -Force
Creating & Removing
# Create a directory New-Item -Path "C:\Temp\Logs" -ItemType Directory # Create a file New-Item -Path "C:\Temp\notes.txt" -ItemType File # Write content to file Set-Content -Path "notes.txt" -Value "Line 1" Add-Content -Path "notes.txt" -Value "Line 2" # append # Read content Get-Content "notes.txt" # Copy, move, rename, delete Copy-Item "notes.txt" "backup.txt" Move-Item "backup.txt" "C:\Archive\" Rename-Item "notes.txt" "readme.txt" Remove-Item "readme.txt"
Test & Check
# Does the path exist? Test-Path "C:\Temp\notes.txt" # True or False # Get file details Get-Item "C:\Temp\notes.txt" | Select-Object Name, Length, LastWriteTime
What cmdlet checks whether a file or folder exists at a given path?
Strings & Regex
String manipulation, interpolation, and pattern matching with regular expressions
String Types
# Double quotes → variable expansion (interpolation) $name = "Alice" "Hello, $name!" # "Hello, Alice!" "2 + 2 = $(2 + 2)" # "2 + 2 = 4" (subexpression) # Single quotes → literal strings (no expansion) 'Hello, $name!' # "Hello, $name!" # Here-strings (multiline) $multiline = @" Line one Line two with $name "@
String Methods
$text = " Hello, World! " $text.Trim() # "Hello, World!" $text.ToUpper() # " HELLO, WORLD! " $text.ToLower() # " hello, world! " $text.Replace("World", "PS") # " Hello, PS! " $text.Contains("World") # True $text.Split(",") # [" Hello", " World! "] $text.Substring(2, 5) # "Hello" $text.Length # 17 # String formatting "Total: {0:C2}" -f 1234.5 # "Total: $1,234.50"
Regular Expressions
# -match returns true/false and fills $Matches "Server-DC01" -match "Server-(\w+)" $Matches[1] # "DC01" # -replace with regex "2025-01-15" -replace "(\d{4})-(\d{2})-(\d{2})", '$3/$2/$1' # "15/01/2025" # Select-String (like grep) Get-Content "server.log" | Select-String -Pattern "ERROR" # Count matches (Get-Content "server.log" | Select-String "ERROR").Count
If $city = "Vienna", what does "I live in $city" output?
Objects & Properties
Everything in PowerShell is an object — learn to inspect and use them
Inspecting Objects with Get-Member
Every output in PowerShell is a .NET object with properties (data) and methods (actions). Use Get-Member to explore them.
# See all properties and methods of process objects Get-Process | Get-Member # See just properties Get-Process | Get-Member -MemberType Property # Access properties directly (Get-Process "explorer").Id (Get-Process "explorer").StartTime (Get-Date).DayOfWeek
Creating Custom Objects
# PSCustomObject — the go-to way $server = [PSCustomObject]@{ Name = "DC01" IP = "192.168.1.10" OS = "Windows Server 2022" Online = $true } $server.Name # "DC01" $server | Format-List # Array of custom objects $inventory = @( [PSCustomObject]@{ Name="DC01"; Role="Domain Controller" } [PSCustomObject]@{ Name="WEB01"; Role="Web Server" } [PSCustomObject]@{ Name="DB01"; Role="Database" } ) $inventory | Format-Table -AutoSize
Calculated Properties
# Add a calculated column to output Get-Process | Select-Object Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet64 / 1MB, 2) }} | Sort-Object MemoryMB -Descending | Select-Object -First 10
What cmdlet do you pipe output to in order to see all available properties and methods on an object?
Cheat Sheet
Quick reference for the most commonly used PowerShell commands and patterns
📂 File System
Get-ChildItem -Recurse
New-Item -ItemType Directory
Copy-Item src dst
Test-Path "C:\file.txt"
Get-Content file.txt
Set-Content / Add-Content
🔍 Discovery
Get-Command *keyword*
Get-Help cmdlet -Examples
Get-Member
Get-Verb
$var.GetType()
📊 Pipeline
Where-Object { $_.X -eq Y }
Select-Object -First 5
Sort-Object Property
ForEach-Object { ... }
Group-Object Property
Measure-Object -Sum
⚡ Processes & Services
Get-Process
Stop-Process -Name "app"
Get-Service
Restart-Service "svc"
Get-EventLog -LogName System
🔤 String Operations
"Hello $var"
'Literal $var'
$s.Split(",").Trim()
"text" -match "regex"
"text" -replace "a","b"
Select-String -Pattern "x"
📦 Data Export
Export-Csv -Path out.csv
Import-Csv -Path in.csv
ConvertTo-Json
ConvertFrom-Json
Out-File -Path log.txt
Export-Clixml / Import-Clixml
🌐 Networking
Test-Connection "host"
Invoke-WebRequest "url"
Invoke-RestMethod "api"
Resolve-DnsName "host"
Get-NetIPAddress
🛡️ Error Handling
try { ... } catch { ... }
$Error[0]
-ErrorAction Stop
$_.Exception.Message
finally { ... }
Final Quiz
Test your PowerShell knowledge — 8 questions covering everything you've learned