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.

💡 Key Insight

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

VersionNamePlatformNotes
1.0 – 5.1Windows PowerShellWindows onlyShips with Windows, built on .NET Framework
6.0+PowerShell CoreCross-platformOpen-source, built on .NET Core
7.xPowerShell 7Cross-platformCurrent recommended version

Your First Command

Open a PowerShell terminal and type:

PowerShell
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.

Exercise 1 Your First Cmdlet

What cmdlet would you use to display the current date and time? Type it below.

PowerShell
PS >

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.

VerbPurposeExamples
GetRetrieve dataGet-Process, Get-Service, Get-ChildItem
SetModify dataSet-Location, Set-Variable, Set-Content
NewCreate somethingNew-Item, New-Object, New-Variable
RemoveDelete somethingRemove-Item, Remove-Variable
Start/StopControl executionStart-Process, Stop-Service
Import/ExportData transferImport-Csv, Export-Clixml
InvokeRun an actionInvoke-Command, Invoke-WebRequest

Discovering Commands

PowerShell
# 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
📘 Note

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).

PowerShell
# 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:

AliasFull CmdletOrigin
ls, dirGet-ChildItembash / cmd
cdSet-LocationUniversal
cp, copyCopy-Itembash / cmd
mv, moveMove-Itembash / cmd
rm, delRemove-Itembash / cmd
cat, typeGet-Contentbash / cmd
cls, clearClear-Hostcmd / bash
⚠️ Warning

While aliases make typing faster, always use full cmdlet names in scripts for readability and maintainability.

Exercise 2 Find the Right Cmdlet

What command would you use to get a list of all running services on the system?

PowerShell
PS >

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.

PowerShell
# 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

CmdletPurposeExample
Where-ObjectFilter objects... | Where-Object { $_.CPU -gt 10 }
Select-ObjectChoose properties or count... | Select-Object Name, Id -First 3
Sort-ObjectSort results... | Sort-Object Length -Descending
ForEach-ObjectIterate and transform... | ForEach-Object { $_.Name.ToUpper() }
Measure-ObjectCount, sum, average... | Measure-Object -Sum
Group-ObjectGroup by a property... | Group-Object Extension
Format-TableDisplay as table... | Format-Table -AutoSize
Export-CsvSave to CSV file... | Export-Csv output.csv
💡 The $_ Variable

$_ (or $PSItem) represents the current object in the pipeline. You'll use it constantly inside Where-Object and ForEach-Object script blocks { }.

Exercise 3 Build a Pipeline

Write a pipeline that gets all processes and filters only those where the process name is "svchost". Use Where-Object with $_.Name.

PowerShell
PS >

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.

PowerShell
# 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:

PowerShell
[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

VariableDescription
$_ / $PSItemCurrent pipeline object
$nullNull value
$true / $falseBoolean values
$PWDCurrent working directory
$HOMEUser's home directory
$ErrorArray of recent errors
$PSVersionTablePowerShell version info
$env:PATHEnvironment variables
Exercise 4 Variable Syntax

Create a variable called $greeting and assign it the string "Hello World". Type the full assignment statement.

PowerShell
PS >

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).

OperatorMeaningExample
-eqEqual to5 -eq 5 → True
-neNot equal5 -ne 3 → True
-gtGreater than10 -gt 5 → True
-ltLess than3 -lt 7 → True
-geGreater or equal5 -ge 5 → True
-leLess or equal4 -le 5 → True
-likeWildcard match"hello" -like "hel*" → True
-matchRegex match"abc123" -match "\d+" → True
-containsCollection contains@(1,2,3) -contains 2 → True
-inValue in collection2 -in @(1,2,3) → True
📘 Case Sensitivity

By default, string comparisons are case-insensitive. Prefix with c for case-sensitive: -ceq, -clike, -cmatch.

Logical Operators

PowerShell
# 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)
Exercise 5 Pick the Operator

Which PowerShell operator checks if a string matches a wildcard pattern? (e.g., checking if a filename matches *.txt)

PowerShell
PS >

Control Flow

Conditionals, loops, and flow control to build logic into your scripts

If / ElseIf / Else

PowerShell
$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

PowerShell
$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

PowerShell
# 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
Exercise 6 Write a Loop

Write a foreach loop that iterates over $items and uses Write-Host to print each item. Use $item as the loop variable.

PowerShell
PS >

Functions

Encapsulate reusable logic with parameters and return values

Basic Function

PowerShell
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.

PowerShell
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." }
}
💡 Begin / Process / End

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.

Exercise 7 Function Keyword

What keyword starts a function definition in PowerShell?

PowerShell
PS >

File System Operations

Navigate, create, read, and manipulate files and directories

Navigation & Listing

PowerShell
# 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

PowerShell
# 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

PowerShell
# 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
Exercise 8 File Check

What cmdlet checks whether a file or folder exists at a given path?

PowerShell
PS >

Strings & Regex

String manipulation, interpolation, and pattern matching with regular expressions

String Types

PowerShell
# 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

PowerShell
$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

PowerShell
# -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
Exercise 9 String Interpolation

If $city = "Vienna", what does "I live in $city" output?

PowerShell
PS >

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.

PowerShell
# 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

PowerShell
# 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

PowerShell
# 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
Exercise 10 Object Discovery

What cmdlet do you pipe output to in order to see all available properties and methods on an object?

PowerShell
PS >

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