PowerShell Cheat Sheet

Useful Tips and Techniques

Get-Member <var or expression> | Get-Member will display properties and methods of the object piped in; If the object represents a collection, will display properties and methods of the collection member types
Write-Output -NoEnumerate $arrayVar | Get-Member | Format-Table Since Get-Member "unwraps" arrays and shows you details about their member types, you can use this if you want details about the array itself
Find-Module -Command X Find module(s) containing command X
Get-Module Lists modules already loaded in current session
Get-Module -ListAvailable Lists all modules available for import grouped by the various paths in $env.PSModulePath
Get-Command
  [-Name "*search*"]
  [-Module ModName]
Search on available cmdlets
  Search by command name; * = wildcard
  -Module "x" limits output to commands from x
Get-Help <cmdlet> -Full
  -Online
Get full help for cmdlet (must first download)
  Open the web doc for the cmdlet instead
Start-Process powershell -Verb runAs Start a new PS5 window as the same user with elevated privileges; run on 'pwsh' instead for PS7
Ctrl + C Force-exit currently running command or process
Show-Command Do-Thing Get an interactive GUI for all args of Do-Thing
Get-Thing | Grid-View Get a GUI for examining piped object / output
Where-Object Filter collections by member object properties
$env:PSModulePath See what paths are being used to access modules
$env:PSModulePath += ";<path>" Add a new module path
$PSVersionTable Holds current version of PowerShell
$PSScriptRoot Holds the directory the current script is in
$cmd = "C:\doThing.exe" & $cmd -Arg "arg1" Use the contents of a variable as a command
$someCollection | Select-Object
  -Property SomeProperty
  @{ l="CustomPropertyName"; e={$_.Name + $_.Description} }
Select-Object takes piped input object(s) and produces output object(s) with only the specified properties from the input object.

Add custom properties with custom labels by supplying (as an argument to -Property) a hash table with l or label = "property name", and e or expression = script block for calculating the property value
Add-Member
  -InputObject $someObject
  -NotePropertyMembers
    @{
      MyBool = $false;
      MyString = "mine"
    }
This works on most objects in PowerShell to add custom properties, because most objects are actually wrapped in a PSObject instance.

EXCEPTION: String literals / variables set to string literals are NOT wrapped in PSObject by default, and Add-Member won't work on them. Instead, use $str = [PSObject]::AsPSObject( "my string" )
Write-Host "`rThis message" -NoNewline

Write-Progress ...
`r returns to the beginning of the current line and then the write overwrites existing contents

Achieves a similar goal with less flexibility
$cred = Get-Credential Create a credential object via input prompts with the password stored as a secure string
$cred.GetNetworkCredential() Get a network credential object from the credential object, which allows you to access the password as plain text if needed
$cred.Password | ConvertFrom-SecureString Get encrypted form of password (uses the Windows DPAPI, i.e. will only be decryptable / useable by the same Windows user on the same machine)
[datetime]::FromFileTime($x) Convert a Windows file time value in $x (in ticks) to a DateTime object (e.g. the AD attribute msDS-UserPasswordExpiryTimeComputed)

Variables

$var = "string value"
$a, $b = 0
$a, $b = "a","b"
Assign variable values in the current scope
$Script:var = "value" Assign variable at Script scope
$Global:var = "value" Assign variable at Global scope (PS session)
$var = [int]5 Create/assign strongly typed variable
"This string has a $var" Insert the variable value in the resulting string
"Index 3 is $($arr[3])" Insert an expression in a string
Test-Path "variable:name" Check if variable $name has been initialized at any currently accessible scope
Test-Path "variable:Local:name" Check if variable $name has been initialized at the Local scope (i.e. inside a function)
Test-Path "variable:Script:name" Check if variable $name has been initialized at the Script scope
Test-Path "variable:Global:name" Check if variable $name has been initialized at the Global scope

Arrays and Objects

$arr = "a", "b", "c" Create array of three strings
$arr = 1..10 Create an array with 10 integers, from 1 to 10
$arr = @() Create empty array
$arr[0]; $arr[-1] Access the first array element; last array element
$arr[2,5+-3..-1] Access elements at index 2, 5, and the last three
$both = $arr1 + $arr2 Append arrays into a single resulting array
[PSCustomObject]@{x=1;y=2} Create custom anonymous object
$a = 1,2,3,4; $b = 1,4,5,6
$a + $b | Select-Object -Unique
$a | Where-Object { $b -contains $_ }
$a | Where-Object { $b -notcontains $_ }
$b | Where-Object { $a -notcontains $_ }
List comparison operations:
Union
Intersection
Difference (a - b)
Difference (b - a)

Hash Tables / Dictionaries

$hash = @{} Create empty hash table
$hash = @{ a = 1; x = "blah" } Create hash table with two key/value pairs
$hash["a"] = 4 Get/set/add a hash table value
$hash.Remove( "a" ) Remove key/value pair from hash table

Basic Terms and Syntax

cmdlet Command built into PowerShell written in .NET
function Command written in PowerShell scripting language
Script Executable (typically) PowerShell file; extension: .ps1
`t, `n Tab, Newline (` = escape character, line continuation character)
# Comment Line comment
<# Comment
#>
Multi-line comment
Some‑Command > out.txt    Shortcut for piping to the Out-File command
$_ or $PSItem Variable automatically populated from pipeline input.

Example use: $myArray | ForEach-Object { Write-Host $_.Name } iterates over each element in $myArray and writes the Name property of each one to the console.
Do-It -Do:$true Explicitly pass true/false to a command switch
--% Signals to PowerShell to stop parsing input on the rest of the line as PowerShell. Useful if you're having trouble with PowerShell interfering when doing things like running an .exe with its own input argument syntax.

Example:
& myExe.exe --% /arg "valueWithDolla$ignsOrSomething"
You can use parenthetical subexpressions, e.g. Do-Thing -Arg1 (Get-Arg -SubArg)

Operators

-and, -or, -not, ! Boolean operators
-eq, -ne, -gt, -ge, -lt, -le Comparison operators
NOTE: All string comparisons are case insensitive by default
-replace Substring replacement, e.g.:
  "Funk" -replace "F","St"
  returns Stunk
Works with regex syntax, including match group refs
-like, -notlike Wildcard matching (* = multiple, ? = one), e.g.:
  "Flunk" -like "*u?k"
  returns True
-contains, -notcontains
-in, -notin
Check if a value is in an array, e.g.:
  $temp = "a","b","c"
  $temp -contains "b"
  returns True
  "b" -in $temp
  returns True
-match, -notmatch Regular expression matching, e.g.:
  "Funk" -match "^F[ui]n.$"
  returns True
Populates $Matches with match info in the form of a hash table indexed by the match group numbers (0 = the full match)

Flow Control

if( ) {...}; elseif( ) {...}; else {...} while() {...}; 1..10 | foreach{ $_ }
for( $i=0; $i -lt 10; $i++ ) {...} foreach( $item in $var ) {...}
exit # exit script, even if in a function throw "Manually thrown exception"
$name = Get-Content Env:\COMPUTERNAME
Switch -Wildcard ( $name ) { "Comp*" { Write "starts with Comp"; break; }
Default { Write "Doesn't"; } }
try { Do-Thing -ErrorAction Stop -ErrorVariable $e}
catch { Write-Host $e }
finally { ... }
Try code, stop if error, store error details in $e
If error occurs, run catch block with access to $e
Run finally block whether or not error occurs

Scripting Basics

[CmdletBinding()]
param(
  [Parameter(Mandatory=$True)]
  [string] $ComputerName,
  [int] $DriveType = 3,
  [switch] $IsSwitched
  [ValidateSet( "Test", "Prod" )]
  [string] $Environment,
)
Add parameters to a .ps1 script
Parameters with no default will prompt user
Makes the parameter required
String parameter with no default value
Int parameter with a default value
Switch; check with $IsSwitched.IsPresent
ValidateSet creates an enum-like parameter
<#
.SYNOPSIS
Does a thing.
.DESCRIPTION
Here's more about the thing.
.PARAMETER ParamOne
This parameter does something.
.PARAMETER ParamTwo
This one does something else.
.EXAMPLE
.\Get-Thing -ParamOne localhost
#>
Syntax for adding help to a script (put it at the top)
function PSVerb-Noun { ... } Create a function within a script;
To add args or help, use the same syntaxes as above within the function block
To make your script a module... Make sure it has one or more functions, put it here:
(for Windows PowerShell)
  C:\Users\<you>\Documents\WindowsPowerShell\<your module>\
Get-Help *function* Doc for available features for functions
pwsh.exe -Command & ".\script.ps1" -Arg1 blah Run a script with arguments from the PowerShell executable (use in Win tasks; if pwsh.exe is not in PATH, have to specify the full path to the executable in quotes)

Script Debugging and User Interaction

Write-Verbose Used for output only displayed in verbose mode; script must be executed with -Verbose switch
Write-Debug Outputs debug message and pauses script execution; script must be executed with -Debug
Write-Host "message"
  -ForegroundColor Red
  -NoNewLine
Print output to PowerShell console
  Set text color
  Remove default line break at the end of output
$thing = Read-Host "Enter something"
  -AsSecureString
Print a prompt to console and get user input
  Read as a secure string
Do-Thing -Confirm Force the executing host to manually confirm execution of Do-Thing within the script
Do-Thing -Confirm:$false Override a confirm-by-default command

Jobs

Start-Job -ScriptBlock { ... } Starts a background job; results are tied to the current PS session (close it, and you lose results)
Get-Job Shows all jobs tied to the current session
Wait-Job Wait for one or more session jobs to complete
Receive-Job
  -Id 3
  -Keep
  -Wait
Load results for a background job
  Specifies the Job ID of the job you want
  Keeps results in memory to Receive-Job again
  Bring the job to the foreground session

Misc. Commands of Note

Export-Csv Import-Csv Where-Object
Set-Location Get-Content Copy-Item
Remove-Item New-Item Invoke-Item
Invoke-WebRequest Get-PSDrive Get-ChildItem
Import-Module Compare-Object

Aliases

% ForEach-Object
? Where-Object
> Out-File
ft Format-Table
ipmo Import-Module
select Select-Object
-EA -ErrorAction