Links
Reference
Files
Powershell scripts have a .ps1 extension.
Syntax
# Documentation, information
Update-Help # Update help system - to run as Administrator
help Test-Path # Get help on a command, on an alias...
help Test-Path -full # ... and on all options
help Test-Path -examples # ... see examples. VERY USEFUL. Eg. help save-help examples
Get-Command about_* # DOES NOT WORK
Get-Command -Verb Add
Get-Alias ps # 'Get-Process'
Get-Alias -Definition Get-Process # 'ps'
gal | findstr Get-Process # Unix style
ps | Get-Member
# Options can be abbreviated
Get-Alias -Definition Get-Process
gal -def Get-Process
# Single line comments start with a number symbol.
<#
Multi-line comments
like so
#>
# Frequent aliases (sorted by definition)
# % -> ForEach-Object
# foreach -> ForEach-Object
# alias -> Get-Alias
# gal -> Get-Alias
# dir -> Get-ChildItem
# ls -> Get-ChildItem
# gci -> Get-ChildItem
# gcm -> Get-Command
# cat -> Get-Content
# type -> Get-Content
# help -> Get-Help
# gm -> Get-Member
# ps -> Get-Process
# man -> help
# ni -> New-Item
# md -> New-Item
# mkdir -> New-Item
# del -> Remove-Item
# erase -> Remove-Item
# rd -> Remove-Item
# ri -> Remove-Item
# rm -> Remove-Item
# rmdir -> Remove-Item
# where -> Where-Object
# echo -> Write-Output
# write -> Write-Output
Primitive types / operators
# Numbers
3
1 + 1 # 2
2 - 1 # 1
10 * 2 # 20
10 / 2 # 5
10 / 3 # 3.3333333
[int](10 / 3) # 3
[int]1.5 -eq [int]2.5 # True !
10 % 3 # 1
[Math]::Pow(2,3) # 8
# Boolean
$True # True
$False # False
!$True # False
-not $True # False
$True -and $True
$False -or $False
0 -eq $False # True
2 -ne $True # True
[bool](0) # False
# Bitwise
0 -band 2 # 0
-5 -bor 0 # -5
# Comparison
1 -eq 1
1 -ne 0
0 -lt 1
1 -le 1
1 -gt 0
1 -ge 1
# With objects
"foo" -eq "foo" # True
"foo" -eq "FOO" # True, insensitive!
"foo" -ceq "FOO" # False
"a" -clt "A" # True ! (strange)
(1,2,3,1,1) -eq 1 # 1,1,1
@{"a"=1} -eq @{"a"=1} # False !
# Type, Typecast, -is, GetType()
[int]2.5 # 2
[bool]5 # True
$b = (3,4)
(1,2) -is $b.GetType() # True
Strings / arrays / hashtables / ...
# Strings
$hello = "Hello"
$world = "World"
'Hello, World!' # No interpolation
"Hello, $world!" # 'Hello, World!'
"Hello, World!".Length # Length
"{0}, {1}!" -f $hello, $world # f-string
"$world is $($world.length) char long"
'Hello, World!'[0] # 'H'
'Hello, World!'[0..5] # 'H', 'e', 'l', 'l', 'o'
'Hello, World!'[0,2,4] # 'H', 'l', 'o'
'Hello, World!'.Substring(0,5) # 'Hello'
'Hello, ' + 'World!' # 'Hello, World!'
'First line`nSecond line' # Escape with backtick
"foo" | gm # Get all methods / properties
# Arrays
# TBC
# Dictionaries
# TBC
Control flow
# if-then-else
if ($someVar -gt 10) { # Testing variable
Write-Output "..."
}
elseif (-not $(Test-Path "somefile.txt")) { # Testing cmd result
Write-Output "..."
}
else {
Write-Output "..."
}
# foreach
foreach ($animal in ("dog", "cat", "mouse")) {
# You can use -f to interpolate formatted strings
"{0} is a mammal" -f $animal
}
# for
$letters = ('a','b','c','d','e','f','g','h')
for($i=0; $i -le $letters.Count-1; $i++){
Write-Host $i, $letters[$i]
}
# while
$x = 0
while ($x -lt 4) {
Write-Output $x
$x += 1 # Shorthand for x = x + 1
}
# switch
$val = "20"
switch($val) {
{ $_ -eq 42 } { "The answer equals 42"; break }
'20' { "Exactly 20"; break }
{ $_ -like 's*' } { "Case insensitive"; break }
{ $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break }
{ $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break }
default { "Others" }
}
# try-catch-finally
try {
throw "This is an error" # Use "throw" to raise an error
}
catch {
Write-Output $Error.ExceptionMessage
}
finally {
Write-Output "We can clean up resources here"
}
IO / Files
# read / write
Write-Output "Hello, World!" # alias: echo, write
"Hello, World!" # ... same!
Write-Host "Hello, World!" # Direct to console!
$foo = $(Write-Host "Hello, World!") # !!! LIKELY BAD !!!
$foo = $(Write-Output "Hello, World!") # Good
$foo = Write-Output "Hello, World!" # Better
$foo = "Hello, World!" # ... same ;-)
$foo = Read-Host "Enter foo"
$bar = Read-Host ("Enter {0}" -f $foo)
# Write to file
$contents = "Hello"
$contents | Out-File "$env:HOMEDRIVE\file.txt"
# Read from a file
$contents = Get-Content "file.txt"
New-Item c:\foo # Create directory
New-Item -Path c:\foo -ItemType Directory # Same
Remove-Item c:\foo # Remove directory
Test-Path c:\foo # 'True'
Copy-Item -Path c:\foo -Destionation c:\bar
New-Item c:\foo\bar -Value c:\baz -ItemType SymbolicLink -Force
# Symbolic link
# Grep-like
gal | findstr Get-Process
gal | where {$_.Definition -eq 'Get-Help'}
dir Alias: | where {$_.Definition -eq 'Get-Help'}
# Iterating on every files in $Path
ls $Path | foreach {$_.Name}
ls $Path | % {$_.Name} # same
# ... size filter
ls $Path | where {$_.Length -ge 2*1024} | % {$_.Name}
# ... same, using get-item
get-item $Path\* | where {$_.Length -ge 2*1024} | % {$_.Name}
Get-Item $Path # Get a file object
(Get-Item $Path).Parent # Get parent directory
(Get-Item $Path).Parent.FullName # ... get path only
(Get-Item $Path).Directory.Parent # ... if $Path is a file
# ... These assumes $Path exists. If not, use Split-Path
Functions
# Functions: keep 'Verb-Noun' convention!
function Add-Numbers { # No explicit args
$args[0] + $args[1]
}
Add-Numbers 1 2 # 3
function Add-Numbers($first,$second) { # Explicit args
$first + $second
}
function Add-Numbers { # Explicit args with type
param( [int]$first, [int]$second )
$first + $second
}
Add-Numbers 1 2 # 3
Add-Numbers -first 1 -second 2 # 3
$res = Add-Numbers 1 2
$res = $(Add-Numbers 1 2)
Exec
dotnet.exe # Start an exe
&"c:\program files\dotnet\dotnet.exe" # With space, use call operator '&' ...
."c:\program files\dotnet\dotnet.exe" # ... or '.'
&"c:\program files\dotnet\dotnet.exe" --help # option outside the quotes
# We can run scriptblocks with '&' (in own scope)
$i = 2
$scriptBlock = { $i=5; Write-Output $i }
& $scriptBlock # 5
$i # 2
# ... but '.' run in current scope
& $scriptBlock # 5
$i # 5
# Testing command success with $? or checking for $null
$res = ... # Some command exec
if ($? -and $res -ne $null) {
Write-Host "Command succeeded"
}
else {
Write-Host "Command failed"
}
Miscellaneous
# Script environment
$MyInvocation.MyCommand
# CommandType Name Version Source
# ----------- ---- ------- ------
# ExternalScript test.ps1 C:\tmp\test.ps1
$MyInvocation.MyCommand.Definition # C:\tmp\test.ps1
# Namespaces
ls "HKLM:\Software\Microsoft\PowerShell\1\ShellIds" # HKLM for registry
"$env:PATH" # Env variables
Tips
Measure execution time of a command
Measure-Command { dir }
Measure-Command { dir | Out-default} # To get output
Measure-Command { choco list }
Update help on offline computers
From MS devblogs:
<source lang="powershell">
- On online computer
New-Item c:\tmp\help
Save-Help -DestinationPath c:\tmp\help -Module * -Force
- On offline computer
- ... transfer files to c:\tmp\help
- ... start powershell in admin (Win-X-A)
Update-Help -SourcePath c:\tmp\help -Module * -Force
</source