What Is PowerShell?
PowerShell is an object-oriented shell and scripting language developed by Microsoft. Unlike CMD’s text-based output, PowerShell passes .NET objects through pipelines. Script files use the .ps1 extension and are used for Windows administration, CI/CD automation, system monitoring, and more.
This article covers PowerShell basic syntax, variables, functions, pipelines, and practical automation scripts.
BAT vs PowerShell Comparison
| Category | BAT (CMD) | PowerShell |
|---|---|---|
| Output method | Text strings | .NET objects |
| Variables | %VAR% | $VAR |
| Pipeline | Passes text | Passes objects (property access available) |
| Error handling | %ERRORLEVEL% | try/catch/finally |
| Functions | Labels + goto | function keyword |
| Module system | None | PowerShell Gallery |
| Cross-platform | Windows only | Windows, macOS, Linux |
Basic Syntax
PowerShell uses Cmdlets in a Verb-Noun format. Variables start with $, and types are automatically inferred.
# Output
Write-Host "Hello, this is PowerShell!" -ForegroundColor Green
# Variable declaration (type auto-inferred)
$name = "PowerShell"
$version = 7.4
$today = Get-Date
Write-Host "Name: $name, Version: $version"
Write-Host "Today's date: $($today.ToString('yyyy-MM-dd HH:mm'))"
# Arrays and hashtables
$fruits = @("Apple", "Banana", "Grape")
$config = @{
Host = "localhost"
Port = 8080
Debug = $true
}
Write-Host "First fruit: $($fruits[0])" # Apple
Write-Host "Port: $($config.Port)" # 8080
Use double quotes (") to reference variables inside strings. Single quotes (') output the text literally without interpreting variables. Wrap complex expressions with $().
Pipelines and Objects
PowerShell’s most powerful feature is the object pipeline. When connecting Cmdlets with the | operator, objects (not text) are passed, allowing direct property access.
# Get top 5 processes by memory usage
Get-Process |
Sort-Object WorkingSet64 -Descending |
Select-Object -First 5 Name, @{N='Memory(MB)'; E={[math]::Round($_.WorkingSet64/1MB, 1)}} |
Format-Table -AutoSize
# Sample output:
# Name Memory(MB)
# ---- ----------
# chrome 1024.3
# code 512.7
# explorer 256.1
# Search for files with specific extension + sum their sizes
$totalSize = Get-ChildItem -Path "C:\Projects" -Recurse -Filter "*.log" |
Measure-Object -Property Length -Sum
Write-Host "Total log file size: $([math]::Round($totalSize.Sum/1MB, 2)) MB"
Get-Process returns process objects, and Sort-Object sorts by the WorkingSet64 property. Tasks that require text parsing in BAT are solved with simple property access in PowerShell.
Conditionals, Loops, and Functions
PowerShell provides control structures similar to C# syntax.
# === Conditionals ===
$score = 85
if ($score -ge 90) {
Write-Host "Grade A"
} elseif ($score -ge 80) {
Write-Host "Grade B" # Grade B
} else {
Write-Host "Grade C or below"
}
# switch statement
$os = "Windows"
switch ($os) {
"Windows" { Write-Host "Windows detected" }
"Linux" { Write-Host "Linux detected" }
default { Write-Host "Unknown OS" }
}
# === Loops ===
# foreach: iterate over array
$servers = @("web01", "web02", "db01")
foreach ($server in $servers) {
Write-Host "Checking server: $server"
}
# for: numeric range
for ($i = 1; $i -le 5; $i++) {
Write-Host "Count: $i"
}
# === Functions ===
function Get-DiskUsage {
param(
[string]$DriveLetter = "C" # Default value
)
$disk = Get-PSDrive -Name $DriveLetter
$usedGB = [math]::Round($disk.Used / 1GB, 1)
$freeGB = [math]::Round($disk.Free / 1GB, 1)
return @{ Used = $usedGB; Free = $freeGB }
}
$usage = Get-DiskUsage -DriveLetter "C"
Write-Host "C: Used $($usage.Used)GB / Free $($usage.Free)GB"
Comparison operators use -eq (equal), -ne (not equal), -gt (greater than), -ge (greater or equal), -lt (less than), -le (less or equal). Similar to BAT’s EQU/NEQ but with a hyphen prefix.
| PowerShell | Meaning | BAT Equivalent |
|---|---|---|
-eq | Equal | EQU |
-ne | Not equal | NEQ |
-gt | Greater than | GTR |
-ge | Greater or equal | GEQ |
-lt | Less than | LSS |
-le | Less or equal | LEQ |
-like | Wildcard matching | N/A |
-match | Regex matching | N/A |
Practical Script: Service Monitoring
A script that checks the status of specified services and automatically restarts stopped ones.
# service-monitor.ps1 — service status check and auto-restart
param(
[string[]]$ServiceNames = @("W32Time", "Spooler"),
[string]$LogPath = ".\service-monitor.log"
)
function Write-Log {
param([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$entry = "[$timestamp] $Message"
Add-Content -Path $LogPath -Value $entry
Write-Host $entry
}
Write-Log "=== Service monitoring started ==="
foreach ($svcName in $ServiceNames) {
try {
$service = Get-Service -Name $svcName -ErrorAction Stop
if ($service.Status -eq "Running") {
Write-Log "[OK] $svcName — running normally"
} else {
Write-Log "[WARNING] $svcName — Status: $($service.Status). Attempting restart..."
Start-Service -Name $svcName -ErrorAction Stop
Write-Log "[RECOVERED] $svcName — restart complete"
}
} catch {
Write-Log "[ERROR] $svcName — $($_.Exception.Message)"
}
}
Write-Log "=== Monitoring complete ==="
try/catch handles errors, and -ErrorAction Stop makes non-terminating errors catchable in the catch block. Defining script parameters with param() allows invocation like .\service-monitor.ps1 -ServiceNames "W32Time","Spooler".
Execution Policy Settings
PowerShell blocks script execution by default for security. You must change the execution policy to run PS1 files.
# Check current execution policy
Get-ExecutionPolicy
# Restricted (default — script execution blocked)
# Allow script execution for current user
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# RemoteSigned: allows local scripts, remote scripts require signing
| Policy | Description |
|---|---|
Restricted | Block script execution (default) |
RemoteSigned | Allow local scripts, remote requires signing (recommended) |
Unrestricted | Allow all scripts (not recommended) |
Bypass | No restrictions, no warnings (for CI/CD) |
Summary
PowerShell is a powerful automation tool that goes beyond BAT’s limitations. Key takeaways:
- Object pipeline is the core feature — access data via
.Propertyinstead of text parsing - Variables start with
$, comparisons use hyphen-prefixed operators like-eq/-ne/-gt - Structured error handling with
try/catch/finally - Define script parameters with
param()block - Run
Set-ExecutionPolicy RemoteSignedbefore first use - PowerShell 7+ supports cross-platform on Windows, macOS, and Linux