Photo by chansu shin on Unsplash

On this page

This page is an overview of PowerShell. Windows 10 and later already include Windows PowerShell 5.1. The useful questions are which host you opened, what a command returns, and whether the task belongs in a script.

How it differs from bash

Bash passes text from one program to the next. You cut columns and match lines, and the next program has to understand that text. Shellscripting with Bash is that model.

A PowerShell command is a cmdlet. The name is a verb, a hyphen, and a noun: Get-Service, Stop-Process, Copy-Item. Shared parameters such as -ErrorAction and -WhatIf appear on many commands, so a preview or a stricter error setting is the same flag from one command to the next.

The pipeline carries objects. Get-Service emits a service object. Where-Object reads the Status property. Select-Object keeps the properties you name.

Terminal window
Get-Service | Where-Object Status -eq 'Running' | Select-Object Name, Status
Diagram 1
flowchart LR
  services["Get-Service"] --> running["Where-Object Status"]
  running --> names["Select-Object Name, Status"]

Aliases cover a few bash and Command Prompt names. ls and dir call Get-ChildItem. cd calls Set-Location. In PowerShell, ls does not take bash flags such as -la. The alias is a convenience at the prompt. In a script, write the cmdlet name. Windows PowerShell 5.1 also defines curl as an alias of Invoke-WebRequest, which hides curl.exe. PowerShell 7 does not define that alias. From Windows PowerShell 5.1, call curl.exe when you want the curl program.

Get-Member lists the properties and methods on the objects a command returned:

Terminal window
Get-Service | Get-Member

You learn those property names, then filter and shape them. The same names work for the next command in the pipeline.

Windows PowerShell and PowerShell 7

Two editions are still in use.

Windows PowerShell 5.1 ships with Windows 10 and later, and with Windows Server 2016 and later. It is a component of Windows, so it follows the Windows support lifecycle. It is built on the .NET Framework. The executable is powershell.exe. $PSVersionTable.PSEdition reports Desktop. Microsoft no longer adds features to it. Windows PowerShell versions below 5.1 are unsupported.

PowerShell 7 is the current product. It is built on .NET, released under the MIT license, and installed beside 5.1. The executable is pwsh (pwsh.exe on Windows). $PSVersionTable.PSEdition reports Core. “PowerShell Core” was the product name for version 6. Microsoft dropped that name with PowerShell 7.0. The Core edition value remains, so a script can still tell the hosts apart.

See which host you are in:

Terminal window
$PSVersionTable

Read PSVersion and PSEdition.

For new scripts, install the latest update on the PowerShell 7.6 long-term support line. PowerShell 7 can load many Windows modules that still need the .NET Framework through the Windows PowerShell compatibility feature. That feature runs the module in a local 5.1 session and returns serialized objects, so it needs Windows PowerShell 5.1 on the same computer. Use powershell.exe when a module or a script still needs 5.1 and that compatibility session does not cover it.

Where the language came from

Jeffrey Snover, PowerShell’s inventor, wrote the Monad Manifesto on 8 August 2002. Monad was the design for an administration shell on .NET: cmdlets, a shell, and remote scripting. Microsoft announced the rename to Windows PowerShell on 25 April 2006. The PowerShell team announced Windows PowerShell 1.0 on 14 November 2006.

Windows PowerShell 5.1 followed in August 2016, with the Windows 10 Anniversary Update and Windows Server 2016. On 18 August 2016 Microsoft published the source under the MIT license and alpha builds for Ubuntu, CentOS, Red Hat, and Mac OS X. PowerShell 6.0 was the first supported cross-platform release. The project changelog dates it 10 January 2018, the day the team announced general availability. Microsoft’s support lifecycle dates the release 20 January 2018, the day the GitHub release was published.

PowerShell 7.0, released 4 March 2020, dropped “Core” from the product name. The current long-term support line is 7.6, first released 18 March 2026, built on .NET 10, and supported until 14 November 2028. At the time of writing, the latest update on that line is 7.6.9, published 25 October 2026. PowerShell 7.5 and the previous long-term line, 7.4, are both supported until 10 November 2026. Microsoft supports the latest update of a release. PowerShell 7.7.0-rc.1, published 29 October 2026, is a pre-release. Preview releases are not supported for production.

Release Date Role
Windows PowerShell 1.0 14 November 2006 First shipping release
Windows PowerShell 5.1 August 2016 The edition current Windows includes
PowerShell 6.0 20 January 2018 First supported cross-platform release
PowerShell 7.0 4 March 2020 Product name drops “Core”
PowerShell 7.6.9 25 October 2026 Latest update on the 7.6 long-term line

Not only Windows

PowerShell 7 runs on Windows, macOS, and Linux, on the operating system versions Microsoft supports for that release. Windows PowerShell 5.1 runs on Windows only, because it needs the .NET Framework.

The same .ps1 file can list files, filter objects, and call a web API on each supported system. Commands that talk to Windows stay on Windows. That includes the Registry provider, many role modules that ship with Windows, and APIs that exist only in the .NET Framework. A script that uses those fails on macOS and Linux, including when the host is PowerShell 7.

Remoting splits the same way. Windows remoting uses WinRM. PowerShell 6 and later can also remote over SSH, which is how a session reaches Linux and macOS hosts.

Commands worth knowing

These ten cmdlets cover finding a command, moving around the disk, and reading processes and services. Names in parentheses are aliases you can type at the prompt.

Command What you use it for
Get-Help Help for a command. Get-Help Get-Service -Examples shows samples. Update-Help downloads the fuller help files. On Windows, updating the shared help files needs an elevated session.
Get-Command Finds commands by name, verb, or noun. Get-Command -Noun Service lists the service cmdlets.
Get-ChildItem (dir, ls) Lists files and folders.
Set-Location (cd) Changes the current directory.
Copy-Item (copy, cp) Copies files and folders.
Remove-Item (del, rm) Deletes files and folders. -WhatIf previews the delete.
Get-Content (gc, cat) Reads a file.
Get-Process (ps) Lists processes. Stop-Process ends one.
Get-Service Lists services. Start-Service and Stop-Service change the state.
Where-Object (where) Keeps pipeline objects that match a property test.

Select-Object sits next to Where-Object. One filters objects. The other chooses properties. Get-Member tells you the property names both of them can use.

Scripts

Bash runs a bash script. PowerShell runs a PowerShell script: a text file with the extension .ps1. Shared commands live in a module file, .psm1. A module manifest, and a file that holds data, uses .psd1.

PowerShell does not run a file from the current directory when you type only its name. Pass a path:

Terminal window
./backup-notes.ps1 -Source $HOME/notes

From Command Prompt, a scheduler, or another program, name the host. pwsh -File runs the script in PowerShell 7. powershell.exe -File runs it in Windows PowerShell 5.1.

Terminal window
pwsh -File ./backup-notes.ps1 -Source $HOME/notes

On Linux and macOS the file can start with #!/usr/bin/env pwsh. The kernel uses that line to find PowerShell. PowerShell treats # as a comment, so the same line is skipped when Windows runs the file with -File. The file needs execute permission before the kernel will start it that way.

backup-notes.ps1
#!/usr/bin/env pwsh
param(
[Parameter(Mandatory)]
[string] $Source
)
$dest = Join-Path $HOME 'notes-backup'
New-Item -ItemType Directory -Path $dest -Force | Out-Null
$cutoff = (Get-Date).AddDays(-7)
Get-ChildItem -Path $Source -File |
Where-Object LastWriteTime -gt $cutoff |
ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination $dest
}

The script copies files modified in the last seven days. -Force on New-Item creates notes-backup under your home directory when that folder is missing, and leaves it alone when it is already there. Add -WhatIf to Copy-Item when you want to preview the copy.

On Windows, the execution policy decides whether a script file may run. Microsoft describes it as defense in depth. A person who can type commands can paste the script at the prompt. If no policy is set in any scope, Windows clients use Restricted: commands run, and script files do not. Windows Server uses RemoteSigned: scripts written on the computer run, and a script downloaded from the internet needs a trusted signature or Unblock-File. Group Policy can set another policy, and that setting wins. On Linux and macOS, Get-ExecutionPolicy returns Unrestricted and PowerShell does not enforce the policy.

Windows PowerShell and PowerShell 7 keep separate policies. Get-ExecutionPolicy reports the host you are in. On a Windows client, this allows your own scripts in the current user scope:

Terminal window
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Changing the LocalMachine scope needs an elevated session. A profile is a .ps1 that runs when the shell starts. $PROFILE is its path. A Restricted policy skips that file too.

When to learn it

Learn PowerShell when the work is administration and it repeats.

That includes Windows and Windows Server: services, processes, files, the registry, event logs, and scheduled tasks. It includes Microsoft services that publish a module, such as Azure and Microsoft Graph. It includes a team that wants one language on Windows build agents and on Linux. That choice is PowerShell 7, because Windows PowerShell 5.1 cannot leave Windows.

Stay with bash when the machines and the existing scripts are bash. Shellscripting with Bash covers that work. PowerShell 7 can sit on those machines as a second shell. A bash script stays a bash script.

PowerShell is a poor first language for a website or a desktop application you ship as a product. The shell can call .NET, which is what automation needs. A product interface or a long-running service belongs in a language built for that program.

What it can and cannot do

PowerShell can:

  • Run interactively, and run the same commands from a .ps1 file.
  • Pass objects through a pipeline, and call .NET methods on those objects.
  • Manage Windows through cmdlets and modules, and start other Windows programs when no cmdlet covers the task. Resetting Windows files and folder permissions is icacls, run from an elevated prompt.
  • Call an HTTP API. Invoke-RestMethod turns JSON into objects. Reach other machines with WinRM on Windows, or with SSH in PowerShell 6 and later.
  • Load a product module. The module adds that product’s commands. It does not install another edition of PowerShell.

PowerShell cannot:

  • Run a bash script as bash. The languages differ, and so do the pipelines.
  • Invent a command for a setting that has no cmdlet, no supported API, and no program you can start. Some Windows tasks remain a GUI.
  • Run Windows-only modules, or APIs that exist only in the .NET Framework, on macOS or Linux.
  • Compile a native executable. What you hand someone is a script, a module, or a command that starts pwsh.
  • Use the execution policy as a wall around the machine. The policy stops an accidental script. It does not stop someone who can already run commands.
  • Guarantee that a Windows PowerShell 5.1 script runs unchanged on PowerShell 7, or the reverse. The language is close. Modules and the .NET libraries underneath them are where scripts break.

Check your understanding

Question 1 of 7

0 of 7 checked

  1. 1. What does a PowerShell pipeline pass from one command to the next?

Search articles

Type a word to search published articles.

Open the search page