👑 Premium Sign in Sign up

Language lab · Beginner → Ops

💠 PowerShell

Concept → trace → write code → run tests → explain why → improve → mini-project. Start in the browser if you like; set up your own computer when you are ready.

💻 Runs on your computerOfficial download & docs ↗

📖 Topics with real code (15)

Every verified output below was produced by running the code with PowerShell 7.4.2 on 5 Nov 2026. Open a topic to edit the code and run it on your own computer with the real compiler, through the free GayaGnan agent.

🌱 Beginner (5)

Variables and types

Variables start with $. PowerShell works with .NET objects, so values keep real types: [int], [double], [bool], [string]. GetType() shows the type; a cast like [int]"88" converts.

$age = 15
$height = 1.62
$isStudent = $true
$name = "Asha"
"$name $age $height $isStudent"
"$($age.GetType().Name) $($height.GetType().Name) $($isStudent.GetType().Name) $($name.GetType().Name)"
[int]"88" + 2
"7 / 2 = $(7 / 2), truncated $([math]::Truncate(7 / 2)), [int]9.6 rounds to $([int]9.6)"
[int]::MaxValue

✅ Verified output

Asha 15 1.62 True
Int32 Double Boolean String
90
7 / 2 = 3.5, truncated 3, [int]9.6 rounds to 10
2147483647
Operators and boolean logic

Comparison operators are words: -eq -ne -gt -lt -ge -le, plus -like and -match for text. Logical: -and -or -not. Comparisons ignore case unless you use -ceq.

$a = 17; $b = 5
"$($a + $b) $($a - $b) $($a * $b) $($a / $b) $($a % $b) $([math]::Pow($a, 2))"
"17 -gt 5: $($a -gt $b)  'ABC' -eq 'abc': $('ABC' -eq 'abc')  -ceq: $('ABC' -ceq 'abc')"
$hasTicket = $true; $isVip = $false
"enter: $($hasTicket -and -not $isVip)  either: $($hasTicket -or $isVip)"
"report.pdf" -like "*.pdf"
"roll R42" -match "R(\d+)"; "matched number: $($Matches[1])"

✅ Verified output

22 12 85 3.4 2 289
17 -gt 5: True  'ABC' -eq 'abc': True  -ceq: False
enter: True  either: True
True
True
matched number: 42
Conditionals: if and switch

if/elseif/else picks a branch. switch can match exact values, wildcards (-Wildcard) or regex (-Regex), and can loop over a list.

$marks = 78
if ($marks -ge 90) { $grade = "A+" }
elseif ($marks -ge 75) { $grade = "A" }
elseif ($marks -ge 35) { $grade = "Pass" }
else { $grade = "Fail" }
"Grade: $grade"
switch -Wildcard ("report.pdf", "photo.jpg", "notes.txt") {
    "*.pdf" { "$_ -> document" }
    "*.jpg" { "$_ -> image" }
    default { "$_ -> other" }
}

✅ Verified output

Grade: A
report.pdf -> document
photo.jpg -> image
notes.txt -> other
Loops: for, foreach, while and the pipeline

foreach walks a collection; ForEach-Object processes pipeline items one by one ($_ is the current item). 1..5 makes a range.

for ($i = 1; $i -le 5; $i++) {
    if ($i -eq 3) { continue }
    "for $i"
}
$n = 10
while ($n -gt 0) {
    if ($n -lt 4) { break }
    "while $n"
    $n -= 3
}
foreach ($c in "red", "green") { "foreach $c" }
1..3 | ForEach-Object { ($_ * 10).ToString().PadLeft(4) }

✅ Verified output

for 1
for 2
for 4
for 5
while 10
while 7
while 4
foreach red
foreach green
  10
  20
  30
Functions and parameters

A function has a param() block with types, defaults and [Parameter(Mandatory)]. Anything written to the output is the return value.

function Get-Area {
    param([int]$Length, [int]$Width = 1)
    $Length * $Width
}
function Get-Average {
    param([Parameter(Mandatory)][int[]]$Numbers)
    ($Numbers | Measure-Object -Average).Average
}
"area $(Get-Area -Length 5 -Width 3) and $(Get-Area 7)"
"average $(Get-Average -Numbers 4, 9, 2, 7)"
function Test-Even([int]$n) { $n % 2 -eq 0 }
"10 even? $(Test-Even 10)  7 even? $(Test-Even 7)"

✅ Verified output

area 15 and 7
average 5.5
10 even? True  7 even? False

🌿 Intermediate (6)

Arrays and the pipeline

@() makes an array; += adds (by copying). Where-Object filters, Sort-Object sorts, Measure-Object counts and sums.

$marks = @(72, 95, 64, 88)
$marks += 91
$sorted = $marks | Sort-Object
"sorted: $sorted  first: $($sorted[0])  last: $($sorted[-1])  count: $($marks.Count)"
$high = $marks | Where-Object { $_ -ge 80 }
"80 and above: $high"
$stats = $marks | Measure-Object -Sum -Average -Maximum
"sum $($stats.Sum) avg $($stats.Average) max $($stats.Maximum)"
"odd squares: $((1..5 | Where-Object { $_ % 2 } | ForEach-Object { $_ * $_ }) -join ', ')"

✅ Verified output

sorted: 64 72 88 91 95  first: 64  last: 95  count: 5
80 and above: 95 88 91
sum 410 avg 82 max 95
odd squares: 1, 9, 25
Strings and formatting

Double quotes expand variables and $( ) expressions. -f formats like String.Format. .NET string methods (Trim, Replace, Split, ToUpper) all work.

$t = "  GayaGnan learning  ".Trim()
"$($t.ToUpper()) | $($t.Replace('learning', 'labs')) | $($t.Length)"
$words = $t.Split(" ")
$words -join "-"
"Total: {0:N2} for {1} items" -f (49.5 * 3), 3
'single quotes do not expand $t'
$here = @"
Name: $t
Line two
"@
$here

✅ Verified output

GAYAGNAN LEARNING | GayaGnan labs | 17
GayaGnan-learning
Total: 148.50 for 3 items
single quotes do not expand $t
Name: GayaGnan learning
Line two
Hashtables and custom objects

@{} makes a hashtable (key-value). [ordered] keeps insertion order. [PSCustomObject] turns a hashtable into an object with properties, which tables and CSV understand.

$stock = [ordered]@{ pen = 40; book = 12 }
$stock["eraser"] = 25
$stock.pen -= 5
$stock.GetEnumerator() | ForEach-Object { "$($_.Key) $($_.Value)" }
"has ruler? $($stock.Contains('ruler'))"
$students = @(
    [PSCustomObject]@{ Name = "Asha"; Marks = 88 }
    [PSCustomObject]@{ Name = "Ravi"; Marks = 95 }
)
$students | Sort-Object Marks -Descending | Format-Table -AutoSize | Out-String -Width 60
"the cat and the hat" -split " " | Group-Object | Sort-Object Name | ForEach-Object { "$($_.Name)=$($_.Count)" }

✅ Verified output

pen 35
book 12
eraser 25
has ruler? False

Name Marks
---- -----
Ravi    95
Asha    88


and=1
cat=1
hat=1
the=2
Classes in PowerShell

PowerShell 5+ supports classes with typed properties, constructors, methods and inheritance.

class BankAccount {
    [string]$Owner
    hidden [decimal]$Balance
    BankAccount([string]$owner, [decimal]$balance) { $this.Owner = $owner; $this.Balance = $balance }
    [void] Deposit([decimal]$amount) {
        if ($amount -le 0) { throw "amount must be positive" }
        $this.Balance += $amount
    }
    [decimal] GetBalance() { return $this.Balance }
}
class Savings : BankAccount {
    Savings([string]$o) : base($o, 0) {}
    [void] AddInterest() { $this.Deposit($this.GetBalance() * 0.05) }
}
$acc = [BankAccount]::new("Asha", 500)
$acc.Deposit(250)
"$($acc.Owner) $($acc.GetBalance())"
$s = [Savings]::new("Ravi"); $s.Deposit(1000); $s.AddInterest()
"$($s.Owner) $($s.GetBalance())"

✅ Verified output

Asha 750
Ravi 1050.00
Errors: try/catch, -ErrorAction and $Error

Terminating errors go to catch. Many cmdlets write non-terminating errors; -ErrorAction Stop turns them into catchable ones.

try {
    Get-Item (Join-Path ([System.IO.Path]::GetTempPath()) "no-such-file.txt") -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
    "not found (caught)"
} finally {
    "finally always runs"
}
try { 1 / 0 } catch { "error: $($_.Exception.GetType().Name)" }
try { throw [System.ArgumentException]::new("age must be 0-120") } catch [System.ArgumentException] { "ArgumentException: $($_.Exception.Message)" }
Get-Item (Join-Path ([System.IO.Path]::GetTempPath()) "also-missing.txt") -ErrorAction SilentlyContinue
"after SilentlyContinue, `$? is $?"

✅ Verified output

not found (caught)
finally always runs
error: RuntimeException
ArgumentException: age must be 0-120
after SilentlyContinue, $? is False
Files, JSON and CSV

Set-Content and Get-Content handle text; Export-Csv/Import-Csv turn objects into CSV and back; ConvertTo-Json for APIs. Join-Path builds paths for any OS.

$dir = [System.IO.Path]::GetTempPath()
$csv = Join-Path $dir "marks.csv"
@(
    [PSCustomObject]@{ Name = "Asha"; Marks = 88 }
    [PSCustomObject]@{ Name = "Ravi"; Marks = 95 }
) | Export-Csv $csv -NoTypeInformation
$rows = Import-Csv $csv
$rows | ForEach-Object { "$($_.Name) -> $($_.Marks)" }
"average $(($rows | Measure-Object -Property Marks -Average).Average)"
$rows | ConvertTo-Json -Compress
Remove-Item $csv
"deleted: $(-not (Test-Path $csv))"

✅ Verified output

Asha -> 88
Ravi -> 95
average 91.5
[{"Name":"Asha","Marks":"88"},{"Name":"Ravi","Marks":"95"}]
deleted: True

🌳 Advanced (4)

Recursion and memoization

Functions can call themselves; a script-scope hashtable caches results. [bigint] handles very large numbers.

$script:memo = @{}
function Get-Fib([int]$n) {
    if ($n -lt 2) { return [bigint]$n }
    if ($script:memo.ContainsKey($n)) { return $script:memo[$n] }
    $v = (Get-Fib ($n - 1)) + (Get-Fib ($n - 2))
    $script:memo[$n] = $v
    return $v
}
((0..9 | ForEach-Object { Get-Fib $_ }) -join " ") + " | fib(90) = " + (Get-Fib 90)

✅ Verified output

0 1 1 2 3 5 8 13 21 34 | fib(90) = 2880067194370816120
Script blocks and pipeline functions

A script block { } is a function value; & runs it. A function with begin/process/end and ValueFromPipeline processes pipeline input one item at a time.

$applyTwice = { param($f, $x) & $f (& $f $x) }
& $applyTwice { param($n) $n * 3 } 2
function Measure-Words {
    param([Parameter(ValueFromPipeline)][string]$Line)
    begin { $count = 0 }
    process { $count += ($Line -split '\s+' | Where-Object { $_ }).Count }
    end { "total words: $count" }
}
"the cat sat", "on the mat today" | Measure-Words
$students = @(@{n = "Asha"; m = 88 }, @{n = "Ravi"; m = 95 })
($students | Sort-Object { $_.m } -Descending | ForEach-Object { $_.n }) -join ", "

✅ Verified output

18
total words: 7
Ravi, Asha
Parallel work with ForEach-Object -Parallel

PowerShell 7 runs script blocks on several threads with -Parallel; $using: passes outside variables in. Three 1-second jobs take about 1 second.

$sw = [System.Diagnostics.Stopwatch]::StartNew()
$offset = 100
$results = 1..3 | ForEach-Object -Parallel {
    Start-Sleep -Seconds 1
    $_ * $_ + $using:offset
} -ThrottleLimit 3
"results: $(($results | Sort-Object) -join ', ')"
"took under 2 s: $($sw.Elapsed.TotalSeconds -lt 2)"
$job = Start-ThreadJob { 6 * 7 }
"thread job result: $(Receive-Job $job -Wait)"

✅ Verified output

results: 101, 104, 109
took under 2 s: True
thread job result: 42
Objects, references and copies

Arrays and objects are .NET references: two variables can point to one object. Clone() copies an array; [PSCustomObject].psobject.Copy() copies an object.

$a = @(1, 2, 3)
$b = $a
$c = $a.Clone()
$a[0] = 99
"a $a | b $b | c $c"
$o1 = [PSCustomObject]@{ X = 1 }
$o2 = $o1
$o3 = $o1.psobject.Copy()
$o1.X = 50
"o2.X $($o2.X) (shared) o3.X $($o3.X) (copy)"
"same object: $([object]::ReferenceEquals($o1, $o2))"

✅ Verified output

a 99 2 3 | b 99 2 3 | c 1 2 3
o2.X 50 (shared) o3.X 1 (copy)
same object: True

💻 Terminal on my computer

Like a cloud shell, but on your own laptop: install compilers and run real commands from this page through the free GayaGnan agent. It asks you before connecting, installing or running anything.

🛠️ Set up and verify

  1. Install
    winget install Microsoft.PowerShell
    brew install --cask powershell
    see learn.microsoft.com (Install PowerShell on Linux)
  2. Editor: Visual Studio Code with PowerShell (Microsoft), PSScriptAnalyzer.
  3. Create hello.ps1
    Write-Output 'Hello, GayaGnan!'
  4. Run it and check the version
    pwsh ./hello.ps1
    pwsh -Version
  5. Health check: paste what your terminal printed.

Install one language at a time. These commands only install or print versions; nothing here deletes files. Versions change: check the official page and note the version you installed.

🧭 The 14-lab path

  • 00 · Setup and verify — install the runtime and editor, run hello world, print the version, fix PATH
  • 01 · Syntax and trace — follow each line and the value of every variable
  • 02 · Logic — conditionals and decision trees
  • 03 · Loops — trace tables and loop challenges
  • 04 · Functions — break problems down and test each piece
  • 05 · Data structures — lists, maps, stacks, queues and trees you can see
  • 06 · Debugging — bug cases with a hint ladder
  • 07 · Algorithms — search, sort and Big-O comparison
  • 08 · Files and data — read and write fixture files 🧪 Bash & PowerShell Automation
  • 09 · API or database — talk to a mock API or a sandbox database
  • 10 · Testing — write tests and read failing assertions
  • 11 · Security — secure coding and dependency hygiene for this language
  • 12 · Project — one portfolio mini-project
  • 13 · Assessment — quiz, coding test, rubric and an explain-your-answer prompt

📚 Modules

  1. objects and the pipeline
  2. variables
  3. conditions
  4. loops
  5. functions
  6. modules
  7. error handling
  8. JSON and CSV
  9. REST calls to a mock endpoint
  10. Pester tests
  11. safe automation

🏗️ Mini-projects

  • Synthetic asset report
  • Config validator
  • Mock cloud tag audit

Projects use synthetic data only.