Introduction to PowerShell
Summary: in this tutorial, you will learn discover what makes powershell unique — an object-oriented shell and scripting language built on .net. understand its history, editions, and why it is the modern standard for windows automation.
Introduction to PowerShell
PowerShell is far more than a replacement for the old Windows Command Prompt. It is a complete automation platform — a shell, a scripting language, and a configuration management framework all rolled into one.
What is PowerShell?
PowerShell is a task-based command-line shell and scripting language built on the .NET framework. Unlike traditional shells that pass strings around, PowerShell works with objects — structured data with properties and methods.
This architectural choice fundamentally changes how you work with command output. In traditional Unix shells, every command outputs text, which you must parse with tools like awk, sed, or cut. These tools are powerful but brittle — if the output format changes (different column widths, reordered fields), your scripts break.
PowerShell eliminates this entire category of problems. Commands return structured .NET objects with named properties and typed data. You access properties by name, filter by exact values, and compose pipelines without string manipulation.
Think of it this way: in Bash, you pipe text between commands and parse it. In PowerShell, you pipe .NET objects — so you never need to worry about column alignment, string splitting, or fragile text parsing.
The Key Difference: Objects vs Text
In a traditional shell, everything is text. This creates constant parsing challenges:
# Bash: text-based pipeline
# ps aux | grep nginx | awk '{print $2}'
# You're parsing strings, hoping columns don't shift
This approach has problems:
- Fragile: If column positions change, your script breaks
- Type-unsafe: Everything is a string; you manually convert to numbers
- Verbose: Extracting data requires complex regex or field splitting
- Error-prone: Whitespace, special characters, and quoting are constant issues
In PowerShell, commands return objects with properties:
# PowerShell: object-based pipeline
Get-Process -Name nginx | Select-Object -Property Id
# You directly access the .Id property — no parsing needed
Why this matters:
- Robust: Property names never change; your code is resilient
- Type-safe: CPU is a decimal, memory is an integer, dates are DateTime objects
- Discoverable: Use
Get-Memberto see all available properties and methods - Composable: Filter and transform objects without text manipulation
This single concept — everything is an object — makes PowerShell fundamentally more powerful and less error-prone than text-based shells. You spend less time parsing output and more time solving problems.
A Brief History
| Year | Milestone |
|---|---|
| 2002 | Jeffrey Snover publishes the "Monad Manifesto" |
| 2006 | PowerShell 1.0 released for Windows XP/Vista/Server 2003 |
| 2009 | PowerShell 2.0 — Remoting, background jobs, modules |
| 2012 | PowerShell 3.0 — Workflows, improved cmdlet discovery |
| 2016 | PowerShell goes open-source on GitHub, Linux and macOS support |
| 2018 | PowerShell Core 6.0 — cross-platform, built on .NET Core |
| 2020 | PowerShell 7.0 — unification of Windows PowerShell and PowerShell Core |
| 2024 | PowerShell 7.4+ — latest stable with performance improvements |
Windows PowerShell (5.1) ships with Windows and is built on .NET Framework. PowerShell 7+ is cross-platform and built on .NET (Core). For new work, always use PowerShell 7+.
Windows PowerShell vs PowerShell 7
Understanding the two "editions" is essential:
| Feature | Windows PowerShell 5.1 | PowerShell 7+ |
|---|---|---|
| Platform | Windows only | Windows, macOS, Linux |
| .NET Runtime | .NET Framework 4.x | .NET 8+ |
| Executable | powershell.exe | pwsh.exe |
| Development | Maintenance only | Active development |
| Side-by-side | Pre-installed | Install separately |
Both can coexist on the same machine! powershell.exe always launches Windows PowerShell 5.1, while pwsh.exe launches PowerShell 7+.
Why Learn PowerShell?
1. Automation at Scale
PowerShell was built for automation. Everything you can click in Windows, you can script in PowerShell — and do it across thousands of machines.
Why this matters:
- Repeatability: Script once, run anywhere, anytime
- Consistency: Eliminate human error from repetitive tasks
- Speed: Automate operations that take hours manually
- Auditing: Scripts provide a clear record of what changed
# Create 100 Active Directory users from a CSV
Import-Csv users.csv | ForEach-Object {
New-ADUser -Name $_.Name -Department $_.Dept -Enabled $true
}
This replaces hours of GUI clicking with a 3-line script that's auditable, repeatable, and version-controlled.
2. Consistent Command Structure
Every PowerShell command follows a Verb-Noun naming convention, making commands predictable and discoverable:
Get-Process # Get running processes
Stop-Process # Stop a process
Get-Service # Get services
Start-Service # Start a service
Get-ChildItem # Get files and folders
Copy-Item # Copy files
This consistency has major advantages:
- Guessable: Need to restart a service? Try
Restart-Service(it exists!) - Discoverable:
Get-Command -Verb Getshows all retrieval commands - Self-documenting: Command names clearly state their purpose
- Approved verbs: PowerShell enforces a standard set of verbs (Get, Set, New, Remove, Start, Stop, etc.)
Once you learn the pattern, you can guess command names and often be right. Compare this to Unix commands like ls, cat, grep — abbreviated names you must memorize.
3. Self-Documenting
PowerShell has the best built-in help system of any shell. Every cmdlet includes documentation, examples, and parameter descriptions:
Get-Help Get-Process -Full # Complete documentation
Get-Help Get-Process -Examples # Just show examples
Get-Command -Verb Get # Find all "Get" commands
Get-Command -Noun *User* # Find commands about users
Why this matters:
- No internet required: Full documentation offline
- Examples included: Most cmdlets have 5-10 real-world examples
- Parameter help:
-Fullshows detailed parameter descriptions - Discoverable: Find commands by verb, noun, or keyword
- Update-Help: Download latest docs with one command
Unlike Unix man pages, PowerShell help is written for humans and includes practical examples you can copy and adapt immediately.
4. Cross-Platform
With PowerShell 7+, your scripts run on Windows, macOS, and Linux:
# This works on all three platforms
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
5. Integration with Everything
PowerShell connects to:
- Azure (Az module)
- AWS (AWS.Tools module)
- Microsoft 365 (Exchange Online, SharePoint, Teams)
- Active Directory (RSAT module)
- SQL Server (SqlServer module)
- REST APIs (Invoke-RestMethod)
- WMI/CIM (for hardware and OS info)
Your First PowerShell Commands
Open a PowerShell terminal and try these:
# What version am I running?
$PSVersionTable
# What's today's date?
Get-Date
# What's my computer name?
$env:COMPUTERNAME # Windows
hostname # Cross-platform
Exploring Objects
This is the most important thing to understand early. Every command returns objects:
# Get the current date
$today = Get-Date
# See what properties and methods it has
$today | Get-Member
# Access specific properties
$today.DayOfWeek
$today.Year
$today.Month
# Call methods
$today.AddDays(30)
$today.ToString("yyyy-MM-dd")
# Get a process and explore its properties
$proc = Get-Process -Name "explorer" | Select-Object -First 1
$proc.Id
$proc.CPU
$proc.WorkingSet64 / 1MB # Memory in MB
Get-Member (or its alias gm) is your best friend. Pipe any command to it to discover what properties and methods are available.
The PowerShell Console
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Tab | Auto-complete commands, parameters, paths |
Ctrl+R | Search command history |
↑ / ↓ | Navigate command history |
Ctrl+C | Cancel running command |
Ctrl+L | Clear screen |
F7 | Show command history window (Windows Terminal) |
Ctrl+Space | Show argument completions |
PSReadLine
PowerShell comes with PSReadLine, which gives you a rich editing experience:
# Search history (press Ctrl+R then type)
# Matching commands appear as you type
# Predictive IntelliSense (PowerShell 7.2+)
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
# List view shows multiple suggestions you can scroll through
Understanding Aliases
PowerShell has built-in aliases for many commands, including aliases that look like Unix commands:
# See all aliases
Get-Alias
# Some common ones
Get-Alias ls # → Get-ChildItem
Get-Alias cd # → Set-Location
Get-Alias cat # → Get-Content
Get-Alias rm # → Remove-Item
Get-Alias echo # → Write-Output
Get-Alias cls # → Clear-Host
Get-Alias pwd # → Get-Location
These aliases behave differently from their Unix counterparts! ls in PowerShell is Get-ChildItem, which returns objects, not text. The parameters are different too. When writing scripts, always use the full cmdlet name.
Execution Policies
PowerShell has a safety feature called execution policies that control which scripts can run:
# Check current policy
Get-ExecutionPolicy
# Common policies:
# Restricted — No scripts can run (Windows default)
# RemoteSigned — Local scripts run; downloaded must be signed
# AllSigned — All scripts must be signed
# Unrestricted — All scripts run (with warnings for downloaded)
# Bypass — Nothing blocked, no warnings
# Set for current user (recommended)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Execution policies are a safety feature, not a security boundary. They protect you from accidentally running untrusted scripts. Set RemoteSigned for your user scope — it's the best balance of usability and safety.
The PowerShell Profile
Your profile is a script that runs every time PowerShell starts — like .bashrc for Bash:
# Check if your profile exists
Test-Path $PROFILE
# See the path to your profile
$PROFILE
# There are actually multiple profiles
$PROFILE | Format-List -Force
# AllUsersAllHosts
# AllUsersCurrentHost
# CurrentUserAllHosts
# CurrentUserCurrentHost ← This is $PROFILE
Create a starter profile:
# Create the profile file if it doesn't exist
if (!(Test-Path $PROFILE)) {
New-Item -ItemType File -Path $PROFILE -Force
}
# Open it in your editor
code $PROFILE
# or: notepad $PROFILE
A starter profile:
# PowerShell Profile
# Aliases
Set-Alias -Name g -Value git
Set-Alias -Name open -Value Invoke-Item
# Quick navigation
function home { Set-Location ~ }
function proj { Set-Location ~/Projects }
# Custom prompt
function prompt {
$path = (Get-Location).Path.Replace($HOME, '~')
Write-Host "PS " -NoNewline -ForegroundColor Cyan
Write-Host "$path" -NoNewline -ForegroundColor Yellow
return "> "
}
# PSReadLine settings
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -EditMode Emacs
Write-Host "Profile loaded!" -ForegroundColor Green
Run each of these commands and observe the output:
$PSVersionTable— what version are you running?Get-Date | Get-Member— how many properties does a DateTime have?Get-Process | Select-Object -First 3— what columns do you see?Get-Alias | Measure-Object— how many aliases are defined?
Show Solution
Sample outputs:
# 1. Version
$PSVersionTable
# PSVersion 7.4.x
# PSEdition Core
# OS Microsoft Windows ...
# 2. DateTime members
Get-Date | Get-Member
# There are roughly 20+ properties (Year, Month, Day, Hour, etc.)
# and 20+ methods (AddDays, AddHours, ToString, etc.)
# 3. Process properties
Get-Process | Select-Object -First 3
# Handles NPM(K) PM(K) WS(K) CPU(s) Id ProcessName
# You see structured columns — each is a property of the object
# 4. Alias count
Get-Alias | Measure-Object
# Count: typically 140-180 aliases depending on modules loaded
Use Get-Date and its members to answer these questions:
- What day of the year is today?
- What date is it 100 days from now?
- Is this year a leap year?
💡 Hint
Get-Date | Get-Member to discover properties and methods. Look for DayOfYear, AddDays(), and IsLeapYear().Show Solution
$today = Get-Date
# 1. Day of the year
$today.DayOfYear
# Example output: 166
# 2. 100 days from now
$today.AddDays(100)
# Example output: Wednesday, September 23, 2025 ...
# 3. Is this a leap year?
[DateTime]::IsLeapYear($today.Year)
# Output: False (2025 is not a leap year)
Written by the ShellRAG Team
The ShellRAG editorial team writes practical, beginner-friendly PowerShell tutorials with tested code examples and real-world use cases. Every article is technically reviewed for accuracy and updated regularly.
Learn more about us →