PowerShell is a command-line shell, scripting language, and automation platform developed by Microsoft. Unlike traditional shells that mainly pass text between commands, PowerShell works with structured .NET objects. This makes it useful for system administration, configuration management, file operations, cloud management, reporting, and repeatable automation.

This PowerShell tutorial explains how to open and install PowerShell, run commands, use the pipeline, work with variables and collections, write scripts and functions, handle errors, manage files and processes, and apply basic scripting practices safely.

What PowerShell Does

PowerShell provides commands called cmdlets for performing administrative and development tasks. A cmdlet normally follows a Verb-Noun naming pattern, such as Get-Process, Set-Location, and Restart-Service.

  • Manage files, folders, processes, services, event logs, and system settings.
  • Automate repetitive administrative tasks with scripts.
  • Query structured data and export reports.
  • Manage Windows, Linux, and macOS systems where supported.
  • Work with Microsoft services, cloud platforms, APIs, and remote computers through suitable modules.
  • Combine native command-line tools with PowerShell cmdlets.
  • Create reusable functions, modules, and scheduled automation.

PowerShell and Windows PowerShell Differences

Windows PowerShell and modern PowerShell are related but distinct products. Windows PowerShell is the Windows-only edition included with many Windows installations. Modern PowerShell is open source, cross-platform, and installed separately on supported systems.

FeatureWindows PowerShellModern PowerShell
Typical executablepowershell.exepwsh
Platform supportWindowsWindows, Linux, and macOS
RuntimeWindows .NET FrameworkModern .NET
Development statusMaintained mainly for compatibilityActively developed
Module compatibilitySupports older Windows-specific modulesSupports cross-platform and compatible modern modules

Some older Windows administration modules require Windows PowerShell, while newer cross-platform modules are designed for modern PowerShell. Check module requirements before selecting an edition for a particular task.

How to Open PowerShell on Windows

PowerShell can be opened from the Start menu, Windows Terminal, the Run dialog, File Explorer, or another command-line shell.

  1. Open the Windows Start menu.
  2. Search for PowerShell or Windows Terminal.
  3. Select the required PowerShell profile.
  4. Use Run as administrator only when the task requires elevated permissions.

To start Windows PowerShell from the Run dialog, press Windows + R, enter the following command, and press Enter:

</>
Copy
powershell

To start modern PowerShell after it has been installed, use:

</>
Copy
pwsh

Installing PowerShell on Windows, macOS, and Linux

Modern PowerShell can be installed separately from Windows PowerShell. Microsoft provides installation methods for Windows, macOS, and supported Linux distributions. Package managers are generally easier to maintain because they can also be used for future updates.

Install PowerShell on Windows with WinGet

</>
Copy
winget search Microsoft.PowerShell
winget install --id Microsoft.PowerShell --source winget

Install PowerShell on macOS with Homebrew

</>
Copy
brew install --cask powershell

Start PowerShell After Installation

</>
Copy
pwsh

Linux installation commands differ by distribution and package source. Use the current Microsoft installation instructions for the operating system and release you are using.

Checking the Installed PowerShell Version

The automatic variable $PSVersionTable shows the installed PowerShell version, edition, platform, operating system, and related compatibility details.

</>
Copy
$PSVersionTable

To display only the PowerShell version, use:

</>
Copy
$PSVersionTable.PSVersion

PowerShell Cmdlet Naming and Command Discovery

PowerShell cmdlets usually follow the Verb-Noun format. The verb indicates the action, and the noun identifies the resource being managed.

CmdletPurpose
Get-ProcessRetrieves running processes
Get-ServiceRetrieves system services
Set-LocationChanges the current location
New-ItemCreates a file, directory, or another supported item
Remove-ItemRemoves an item
Get-ContentReads content from a file

Use Get-Command to discover commands.

</>
Copy
Get-Command
Get-Command -Verb Get
Get-Command -Noun Service
Get-Command *Process*

To see approved PowerShell verbs, run:

</>
Copy
Get-Verb

Getting Help for PowerShell Commands

PowerShell includes a help system that explains syntax, parameters, inputs, outputs, and examples. Help content may need to be downloaded or updated before full details are available.

</>
Copy
Update-Help
Get-Help Get-Process
Get-Help Get-Process -Examples
Get-Help Get-Process -Full
Get-Help Get-Process -Online

Some help updates require administrative permissions. The -Online parameter opens the current online documentation when an online help link is available.

Basic PowerShell Commands for Beginners

CommandPurpose
Get-LocationDisplays the current directory or provider path
Set-LocationChanges the current location
Get-ChildItemLists files, folders, or other child items
New-ItemCreates a new item
Copy-ItemCopies an item
Move-ItemMoves an item
Rename-ItemRenames an item
Remove-ItemRemoves an item
Get-ContentReads file content
Set-ContentReplaces file content
Add-ContentAppends content to a file
Clear-HostClears the terminal display
</>
Copy
Get-Location
Get-ChildItem
Set-Location C:\Users
Get-ChildItem -Force

PowerShell also provides aliases such as cd, dir, and ls. Aliases are convenient at the interactive prompt, but full cmdlet names are clearer in reusable scripts.

PowerShell Parameters and Named Arguments

Parameters modify how a command runs. Named parameters begin with a hyphen and make commands easier to read.

</>
Copy
Get-ChildItem -Path C:\Logs -File -Recurse
Get-Process -Name powershell
Get-Service -Name Spooler

Some parameters accept values, while switch parameters such as -Recurse, -Force, and -WhatIf are enabled by their presence.

How the PowerShell Pipeline Works

The pipeline passes command output to another command using the pipe character, |. In PowerShell, the pipeline usually transfers objects rather than plain text. The receiving command can work directly with object properties and methods.

</>
Copy
Get-Process | Sort-Object CPU -Descending
Get-Service | Where-Object Status -eq 'Running'
Get-ChildItem -Path C:\Logs -File | Measure-Object -Property Length -Sum

The first command retrieves objects, and later commands filter, sort, measure, format, or export those objects.

Inspecting PowerShell Objects with Get-Member

Because PowerShell commands return objects, it is useful to inspect the properties and methods available on those objects. The Get-Member cmdlet displays their structure.

</>
Copy
Get-Process | Get-Member
Get-Service | Get-Member
Get-ChildItem | Get-Member

After identifying an object’s properties, use Select-Object to display only the fields needed for a report.

</>
Copy
Get-Process |
    Select-Object Name, Id, CPU, WorkingSet

Filtering, Sorting, and Selecting PowerShell Objects

PowerShell provides object-aware commands for refining command results.

</>
Copy
Get-Process |
    Where-Object CPU -gt 10 |
    Sort-Object CPU -Descending |
    Select-Object -First 10 Name, Id, CPU
  • Where-Object filters objects.
  • Sort-Object sorts objects by one or more properties.
  • Select-Object chooses properties or limits the number of results.
  • Group-Object groups objects by a property value.
  • Measure-Object counts or calculates numeric totals and averages.

PowerShell Variables and Data Types

A PowerShell variable begins with a dollar sign. PowerShell can infer a variable’s type from its assigned value, or a type can be declared explicitly.

</>
Copy
$name = 'Anita'
$age = 30
$active = $true
$today = Get-Date

[string]$department = 'Finance'
[int]$employeeCount = 25

Use GetType() to inspect the runtime type of a value.

</>
Copy
$employeeCount.GetType()

PowerShell Strings and Variable Expansion

Single-quoted strings are treated literally. Double-quoted strings expand variables and expressions.

</>
Copy
$userName = 'Meera'

'Signed in as $userName'
"Signed in as $userName"
"The current date is $((Get-Date).ToString('yyyy-MM-dd'))"
Signed in as $userName
Signed in as Meera
The current date is 2026-07-22

The subexpression operator, $(), evaluates an expression inside a double-quoted string.

PowerShell Arrays and Hashtables

Arrays store ordered collections of values. Hashtables store key-value pairs.

</>
Copy
$servers = @('server01', 'server02', 'server03')

$employee = @{
    Name       = 'Ravi'
    Department = 'Support'
    Active     = $true
}

$servers[0]
$employee['Department']

PowerShell can also create custom objects for structured output.

</>
Copy
$reportRow = [PSCustomObject]@{
    ComputerName = $env:COMPUTERNAME
    CheckedAt    = Get-Date
    Status       = 'Available'
}

$reportRow

PowerShell Comparison and Logical Operators

PowerShell uses comparison operators such as -eq, -ne, -gt, -ge, -lt, and -le. Logical expressions can be combined with -and, -or, -xor, and -not.

</>
Copy
$freeSpaceGB = 18

if ($freeSpaceGB -lt 10) {
    'Low disk space'
}
elseif ($freeSpaceGB -lt 20) {
    'Monitor disk space'
}
else {
    'Disk space is sufficient'
}

String matching operators include -like, -match, and -contains.

</>
Copy
'server-production-01' -like 'server-*'
'error 404' -match '\d{3}'
@('Admin', 'Editor', 'Viewer') -contains 'Editor'

PowerShell Loops for Repeated Tasks

PowerShell supports foreach, for, while, and do loops.

</>
Copy
$servers = @('server01', 'server02', 'server03')

foreach ($server in $servers) {
    Write-Output "Checking $server"
}
</>
Copy
for ($number = 1; $number -le 5; $number++) {
    Write-Output $number
}
</>
Copy
$attempt = 1

while ($attempt -le 3) {
    Write-Output "Attempt $attempt"
    $attempt++
}

Creating and Running a PowerShell Script

A PowerShell script is a text file with the .ps1 extension. Scripts can contain commands, variables, conditions, loops, functions, comments, and error handling.

Create a file named system-report.ps1 with the following content:

</>
Copy
$report = [PSCustomObject]@{
    ComputerName = $env:COMPUTERNAME
    UserName     = $env:USERNAME
    PowerShell   = $PSVersionTable.PSVersion.ToString()
    CheckedAt    = Get-Date
}

$report | Format-List

Run the script from its directory with:

</>
Copy
.\system-report.ps1

On Linux or macOS, a relative script path commonly uses:

</>
Copy
./system-report.ps1

PowerShell Execution Policy on Windows

Execution policies help prevent accidental script execution on Windows. They are not a complete security boundary and should not replace access control, code review, script signing, or endpoint security.

</>
Copy
Get-ExecutionPolicy
Get-ExecutionPolicy -List

When an organization permits local scripts, a user-scoped policy can be configured without changing the policy for every user:

</>
Copy
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Do not change an execution policy merely to bypass an error. First identify the policy source, organizational requirements, and trustworthiness of the script.

PowerShell Functions and Parameters

A function groups commands into a reusable unit. Parameters allow callers to supply values.

</>
Copy
function Get-Greeting {
    param(
        [Parameter(Mandatory)]
        [string]$Name
    )

    "Hello, $Name"
}

Get-Greeting -Name 'Kiran'
Hello, Kiran

Use approved verbs when naming functions so their purpose is clear and they integrate naturally with PowerShell command discovery.

Advanced PowerShell Function Structure

An advanced function uses [CmdletBinding()] and can support common parameters, validation, pipeline input, and safer change handling.

</>
Copy
function Remove-OldLogFile {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)]
        [string]$Path,

        [ValidateRange(1, 3650)]
        [int]$OlderThanDays = 30
    )

    $cutoffDate = (Get-Date).AddDays(-$OlderThanDays)

    Get-ChildItem -Path $Path -File -Filter '*.log' |
        Where-Object LastWriteTime -lt $cutoffDate |
        ForEach-Object {
            if ($PSCmdlet.ShouldProcess($_.FullName, 'Remove old log file')) {
                Remove-Item -LiteralPath $_.FullName
            }
        }
}

Because the function supports ShouldProcess, it can be tested with -WhatIf before files are removed.

</>
Copy
Remove-OldLogFile -Path C:\Logs -OlderThanDays 60 -WhatIf

Handling Errors in PowerShell Scripts

PowerShell distinguishes between terminating and non-terminating errors. A try and catch block handles terminating errors. For cmdlets that normally produce non-terminating errors, use -ErrorAction Stop when the error must be caught.

</>
Copy
try {
    $content = Get-Content -LiteralPath 'C:\Data\settings.json' -ErrorAction Stop
    Write-Output $content
}
catch [System.Management.Automation.ItemNotFoundException] {
    Write-Warning 'The settings file was not found.'
}
catch {
    Write-Error "Unable to read the settings file: $($_.Exception.Message)"
}
finally {
    Write-Verbose 'File read operation completed.'
}

The current error record is available through $_ inside a catch block.

Write-Output, Write-Host, and PowerShell Output Streams

Write-Output sends objects to the success output stream, allowing them to continue through the pipeline. Write-Host writes information intended for display and should not be used as a substitute for pipeline output.

</>
Copy
Write-Output 'Pipeline value'
Write-Host 'Display message'
Write-Warning 'Warning message'
Write-Error 'Error message'
Write-Verbose 'Verbose message'
Write-Debug 'Debug message'

Verbose and debug messages are shown when their corresponding preferences or common parameters are enabled.

Managing Files and Folders with PowerShell

</>
Copy
New-Item -Path C:\Reports -ItemType Directory
New-Item -Path C:\Reports\summary.txt -ItemType File
Set-Content -Path C:\Reports\summary.txt -Value 'Daily report'
Add-Content -Path C:\Reports\summary.txt -Value 'Completed successfully'
Copy-Item -Path C:\Reports\summary.txt -Destination C:\Reports\summary-backup.txt
Get-Content -Path C:\Reports\summary.txt

Use -LiteralPath when a path may contain characters such as brackets that PowerShell could otherwise interpret as wildcard syntax.

</>
Copy
Get-Content -LiteralPath 'C:\Data\file[1].txt'

Finding Files with PowerShell

The following command finds log files under a directory and sorts them by modification time:

</>
Copy
Get-ChildItem -Path C:\Logs -File -Recurse -Filter '*.log' |
    Sort-Object LastWriteTime -Descending |
    Select-Object FullName, Length, LastWriteTime

To calculate the total size of the matching files:

</>
Copy
$measurement = Get-ChildItem -Path C:\Logs -File -Recurse -Filter '*.log' |
    Measure-Object -Property Length -Sum

[math]::Round($measurement.Sum / 1MB, 2)

Managing Processes and Services with PowerShell

PowerShell can inspect and manage processes and operating-system services. Commands that change service state may require elevated permissions.

</>
Copy
Get-Process
Get-Process -Name notepad
Start-Process notepad
Stop-Process -Name notepad -WhatIf
</>
Copy
Get-Service
Get-Service -Name Spooler
Start-Service -Name Spooler
Restart-Service -Name Spooler

Check the target process or service carefully before using a stop or restart command on a production system.

Importing and Exporting CSV Data with PowerShell

PowerShell can convert objects to CSV rows and reconstruct objects from CSV files.

</>
Copy
Get-Process |
    Select-Object Name, Id, CPU |
    Export-Csv -Path .\processes.csv -NoTypeInformation
</>
Copy
$processReport = Import-Csv -Path .\processes.csv
$processReport | Where-Object Name -like 'p*'

Formatting cmdlets such as Format-Table should normally appear only at the end of an interactive command. Do not place them before Export-Csv, because formatting commands replace the original objects with display-formatting data.

Working with JSON in PowerShell

PowerShell can convert objects to and from JSON, which is useful for configuration files and web APIs.

</>
Copy
$configuration = [PSCustomObject]@{
    Application = 'Inventory'
    Enabled     = $true
    Ports       = @(8080, 8443)
}

$configuration |
    ConvertTo-Json -Depth 5 |
    Set-Content -Path .\configuration.json
</>
Copy
$loadedConfiguration = Get-Content -Path .\configuration.json -Raw |
    ConvertFrom-Json

$loadedConfiguration.Application

Calling REST APIs with PowerShell

Invoke-RestMethod sends HTTP requests and commonly converts JSON responses into PowerShell objects.

</>
Copy
$response = Invoke-RestMethod \
    -Uri 'https://api.example.com/status' \
    -Method Get

$response

Do not hard-code API keys, passwords, or access tokens in scripts committed to source control. Use an approved secret store, environment variable, managed identity, or credential-management system appropriate for the environment.

Installing and Using PowerShell Modules

Modules package cmdlets, functions, variables, and other reusable resources. Use the PowerShell Gallery or another trusted repository to discover modules, and inspect a module before installing it in a sensitive environment.

</>
Copy
Get-Module
Get-Module -ListAvailable
Find-Module -Name Pester
Install-Module -Name Pester -Scope CurrentUser
Import-Module -Name Pester

To inspect the commands exported by a module:

</>
Copy
Get-Command -Module Pester

PowerShell Profiles and Persistent Customization

A PowerShell profile is a script that runs when a PowerShell session starts. Profiles can define functions, aliases, environment settings, and module imports.

</>
Copy
$PROFILE
Test-Path $PROFILE

Create the profile file and its parent directory when they do not already exist:

</>
Copy
$profileDirectory = Split-Path -Parent $PROFILE
New-Item -Path $profileDirectory -ItemType Directory -Force
New-Item -Path $PROFILE -ItemType File -Force

Keep profile code lightweight. Slow network calls or large module imports can delay every new PowerShell session.

PowerShell Remoting Basics

PowerShell remoting runs commands on remote systems through configured remoting transports. The required setup, authentication, firewall rules, and supported commands depend on the operating systems and environment.

</>
Copy
Invoke-Command -ComputerName Server01 -ScriptBlock {
    Get-Service
}

For an interactive remote session on a configured Windows environment:

</>
Copy
Enter-PSSession -ComputerName Server01
Exit-PSSession

Use organization-approved authentication and remoting configuration. Avoid weakening trusted-host or certificate checks simply to make a connection succeed.

PowerShell Security and Safe Script Practices

  • Run PowerShell with standard user permissions unless elevation is required.
  • Review downloaded scripts before executing them.
  • Do not paste unknown commands into an elevated session.
  • Use -WhatIf and -Confirm where supported before destructive operations.
  • Use -LiteralPath for paths containing wildcard characters.
  • Avoid storing plaintext passwords, tokens, and private keys in scripts.
  • Validate file paths, user input, and remote data before using them.
  • Use code signing where organizational policy requires trusted scripts.
  • Restrict permissions on script, configuration, log, and credential files.
  • Record sufficient logs for operational diagnosis without exposing secrets.

Testing Destructive PowerShell Commands with WhatIf

Many commands that modify system state support the -WhatIf parameter. It describes the proposed action without performing it.

</>
Copy
Remove-Item -Path C:\Logs\*.log -WhatIf
Stop-Process -Name notepad -WhatIf
Restart-Service -Name Spooler -WhatIf

After confirming that the command targets the intended resources, rerun it without -WhatIf. Not every command supports this parameter, so verify command help first.

Using Visual Studio Code for PowerShell Scripts

Visual Studio Code with the official PowerShell extension provides syntax highlighting, command completion, script analysis, debugging, and an integrated PowerShell terminal. It is suitable for maintaining scripts larger than a few interactive commands.

  • Save scripts with the .ps1 extension.
  • Use consistent indentation and descriptive variable names.
  • Enable script analysis to identify common quality problems.
  • Set breakpoints to inspect values during execution.
  • Store reusable scripts in source control.
  • Document required modules, permissions, inputs, outputs, and supported platforms.

PowerShell Script Example: Generate a File Report

The following script scans a directory, creates structured file records, and exports them to CSV.

</>
Copy
param(
    [Parameter(Mandatory)]
    [string]$Path,

    [string]$OutputPath = '.\file-report.csv'
)

if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
    throw "Directory not found: $Path"
}

$report = Get-ChildItem -LiteralPath $Path -File -Recurse |
    ForEach-Object {
        [PSCustomObject]@{
            Name          = $_.Name
            FullName      = $_.FullName
            Extension     = $_.Extension
            SizeKB        = [math]::Round($_.Length / 1KB, 2)
            LastWriteTime = $_.LastWriteTime
        }
    }

$report |
    Sort-Object SizeKB -Descending |
    Export-Csv -LiteralPath $OutputPath -NoTypeInformation

Write-Output "Report created at $OutputPath"

Run the script with named parameters:

</>
Copy
.\New-FileReport.ps1 -Path C:\Data -OutputPath C:\Reports\files.csv

Common PowerShell Mistakes to Avoid

  • Using aliases in shared scripts: use full cmdlet names so the script is clear and portable.
  • Formatting too early: keep objects intact until the end of the pipeline.
  • Ignoring command help: verify parameter behavior before running a command that changes system state.
  • Running everything as administrator: elevate only for tasks that require additional permissions.
  • Suppressing every error: handle expected failures and log useful diagnostic information.
  • Using string parsing when object properties exist: inspect results with Get-Member and use structured properties.
  • Hard-coding paths and credentials: use parameters, configuration, environment-aware paths, and approved secret storage.
  • Assuming Windows-only behavior: verify commands, paths, modules, and native tools before running a script across platforms.
  • Deleting resources without a preview: use -WhatIf or a read-only discovery command first.

A Practical PowerShell Learning Path

  1. Learn how to open PowerShell and inspect the installed edition and version.
  2. Practice command discovery with Get-Command and command documentation with Get-Help.
  3. Learn paths, files, folders, processes, and services.
  4. Understand objects, properties, methods, and Get-Member.
  5. Practice the pipeline with filtering, sorting, selecting, grouping, and measurement.
  6. Learn variables, strings, arrays, hashtables, custom objects, conditions, and loops.
  7. Create parameterized .ps1 scripts and reusable functions.
  8. Add validation, error handling, verbose messages, and safe change controls.
  9. Practice CSV, JSON, REST API, and module workflows.
  10. Continue with remoting, scheduled automation, testing, modules, and platform-specific administration.

The official PowerShell documentation contains installation guidance, language references, cmdlet documentation, conceptual articles, and examples. PowerShell’s source code and release information are available through the PowerShell GitHub repository. Community modules can be discovered in the PowerShell Gallery.

PowerShell Practice Exercises

  • List the ten largest files in a directory and display their sizes in megabytes.
  • Export running process names, IDs, and memory usage to a CSV file.
  • Create a function that accepts a directory and returns files older than a specified number of days.
  • Read a JSON configuration file and validate that required properties are present.
  • Use Get-Service to report stopped services without changing their state.
  • Create a script that checks whether a set of paths exists and returns structured results.
  • Add try, catch, and logging to a file-processing script.
  • Create an advanced function that supports -WhatIf before removing temporary files.

Frequently Asked Questions About PowerShell

What exactly does PowerShell do?

PowerShell runs commands and scripts that inspect, configure, and automate systems and services. It can manage files, processes, services, structured data, APIs, remote computers, cloud resources, and many products that provide PowerShell modules.

Is PowerShell only available on Windows?

No. Modern PowerShell runs on supported versions of Windows, Linux, and macOS. Windows PowerShell is a separate Windows-only edition retained for compatibility with older Windows technologies and modules.

Is PowerShell a command prompt or a programming language?

It is both a command-line shell and a scripting language. Commands can be entered interactively, combined through pipelines, or saved in scripts and modules with variables, functions, conditions, loops, classes, and error handling.

Do I need programming experience to learn PowerShell?

No. Beginners can start with command discovery, file operations, and pipelines. Basic programming concepts become useful when moving to conditions, loops, functions, error handling, and larger automation scripts.

Can PowerShell scripts damage a computer?

Yes, a script can modify or delete files, stop services, change configuration, or perform other privileged actions when the user has sufficient access. Review scripts, avoid unnecessary elevation, use trusted sources, validate targets, and test supported commands with -WhatIf where possible.

PowerShell Tutorial Editorial QA Checklist

  • Confirm that Windows PowerShell and modern cross-platform PowerShell are described as separate editions.
  • Verify that installation commands match the documented package and operating-system method.
  • Check that every pipeline example passes usable objects rather than formatted display output.
  • Confirm that commands which remove, stop, restart, or overwrite resources include appropriate safety guidance.
  • Verify that scripts use full cmdlet names instead of unexplained aliases.
  • Check that file examples distinguish -Path from -LiteralPath where wildcard characters may matter.
  • Confirm that exception examples use -ErrorAction Stop when a non-terminating error must be caught.
  • Verify that no example includes real passwords, access tokens, API keys, or private infrastructure details.
  • Check cross-platform examples for Windows-specific paths, commands, modules, and assumptions.
  • Confirm that each newly added WordPress code block uses the appropriate PrismJS language or output class.