PSPowerShell · Lesson 7 of 8

Mini Project: System Info Script

Build a script that gathers system information and outputs a clean, formatted report. Something you could actually run on a new machine.

PowerShell
#!/usr/bin/env pwsh
# sysinfo.ps1 — System information report

function Get-SizeString {
    param([long]$Bytes)
    switch ($Bytes) {
        { $_ -gt 1GB } { return "{0:F1} GB" -f ($_ / 1GB) }
        { $_ -gt 1MB } { return "{0:F1} MB" -f ($_ / 1MB) }
        { $_ -gt 1KB } { return "{0:F1} KB" -f ($_ / 1KB) }
        default        { return "$_ B" }
    }
}

function Write-Section {
    param([string]$Title)
    Write-Host ""
    Write-Host "═══ $Title " -NoNewline -ForegroundColor Cyan
    Write-Host ("═" * (50 - $Title.Length - 5)) -ForegroundColor Cyan
}

Write-Host ""
Write-Host "  SYSTEM INFORMATION REPORT" -ForegroundColor White
Write-Host "  Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray

# ─── Operating System ───────────────────────────────────────────────────────
Write-Section "Operating System"
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
if ($os) {
    Write-Host "  OS:       $($os.Caption)"
    Write-Host "  Version:  $($os.Version)"
    Write-Host "  Uptime:   $([math]::Round((Get-Date - $os.LastBootUpTime).TotalHours, 1)) hours"
} else {
    # Cross-platform fallback
    Write-Host "  Platform: $([System.Runtime.InteropServices.RuntimeInformation]::OSDescription)"
    Write-Host "  PowerShell: $($PSVersionTable.PSVersion)"
}

# ─── CPU ────────────────────────────────────────────────────────────────────
Write-Section "CPU"
$cpu = Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue
if ($cpu) {
    Write-Host "  Name:    $($cpu.Name.Trim())"
    Write-Host "  Cores:   $($cpu.NumberOfCores) cores / $($cpu.NumberOfLogicalProcessors) threads"
    Write-Host "  Speed:   $($cpu.MaxClockSpeed) MHz"
}

# CPU load (cross-platform)
$loadPct = (Get-Process | Measure-Object -Property CPU -Sum).Sum
Write-Host "  CPU Sum: $([math]::Round($loadPct, 1))s (cumulative)"

# ─── Memory ─────────────────────────────────────────────────────────────────
Write-Section "Memory"
if ($os) {
    $totalRAM = $os.TotalVisibleMemorySize * 1KB
    $freeRAM  = $os.FreePhysicalMemory * 1KB
    $usedRAM  = $totalRAM - $freeRAM
    $pctUsed  = [math]::Round(($usedRAM / $totalRAM) * 100)
    Write-Host "  Total:  $(Get-SizeString $totalRAM)"
    Write-Host "  Used:   $(Get-SizeString $usedRAM) ($pctUsed%)"
    Write-Host "  Free:   $(Get-SizeString $freeRAM)"
}

# ─── Disk ───────────────────────────────────────────────────────────────────
Write-Section "Disks"
Get-PSDrive -PSProvider FileSystem | ForEach-Object {
    if ($_.Used -or $_.Free) {
        $total = $_.Used + $_.Free
        $pct   = if ($total -gt 0) { [math]::Round(($_.Used / $total) * 100) } else { 0 }
        Write-Host ("  {0,-6} {1,8} used / {2,8} total ({3}%)" -f `
            "$($_.Name):", (Get-SizeString ($_.Used)), (Get-SizeString $total), $pct)
    }
}

# ─── Top Processes ──────────────────────────────────────────────────────────
Write-Section "Top 5 Processes by Memory"
Get-Process |
    Sort-Object WorkingSet -Descending |
    Select-Object -First 5 |
    ForEach-Object {
        Write-Host ("  {0,-20} {1,8}" -f $_.Name, (Get-SizeString $_.WorkingSet))
    }

# ─── Network ────────────────────────────────────────────────────────────────
Write-Section "Network"
$hostname = [System.Net.Dns]::GetHostName()
Write-Host "  Hostname: $hostname"
[System.Net.Dns]::GetHostAddresses($hostname) |
    Where-Object { $_.AddressFamily -eq "InterNetwork" } |
    ForEach-Object { Write-Host "  IP: $($_.IPAddressToString)" }

Write-Host ""
PowerShell
# Run it:
.sysinfo.ps1

# On Linux/macOS (some sections will be skipped):
pwsh ./sysinfo.ps1