title, homepage, tagline
| title | homepage | tagline |
|---|---|---|
| pwsh-essentials | https://webinstall.dev/pwsh-essentials | meta package for our recommended PowerShell plugins and settings |
To update (replacing the current version) run webi pwsh-essentials.
Cheat Sheet
The tools you need to write PowerShell effectively.
This meta package will install the full set of plugins and settings we recommended.
Table of Contents
- Files
- Mostly Case-Insensitive
- Returns vs Pipeline Streams
- Strict, Trace, & Verbose Modes
- The Call Operator "&"
- curl vs curl.exe
- Script Policies & Preferences
Files
These are the files / directories that are created and/or modified with this install:
~/.config/envman/PATH.env
~/.local/bin/pwsh-fix.ps1
~/.local/bin/pwsh-fmt.ps1
~/.local/bin/pwsh-lint.ps1
~/.local/opt/pwsh/
~/.local/share/powershell/Modules/PSScriptAnalyzer/
Things You MUST Know
There are a few key differences to PowerShell from other scripting and programming languages you may have used in the past.
Knowing these from the start can save you a tonne of headache.
0. PowerShell is Case-Insenstive, Usually
Function and Commandlet names, file paths, and boolean operators are all case-insensitive:
write-host "Hello, World!"
WRITE-HOST "Hello, World!"
Write-Host "HELLO, WORLD!" -eq "hello, world!"
# True
However, raw string and byte functions are case sensitive unless 'CurrentCultureIgnoreCase' is used:
"https://webi.sh".StartsWith("HTTPS://")
# False
"https://webi.sh".StartsWith("HTTPS://", 'CurrentCultureIgnoreCase')
# True
1. PowerShell Doesn't Have Return Values
There's not so much concept of a "return" as a "pipeline stream".
All values which are not assigned to a variable, such as $Foobar - or
$null - are pipelined.
- There are no Return Values
- The
Returnkeyword only serves to exit early. - The result of EVERY command is put into a Pipeline
- You can pick which Pipeline a result is written to:
... | Write-Output(the default)... | Write-Debug... | Write-Verbose... | Write-Information... | Write-Warning... | Write-Error... | Write-Host(forced console output, no Pipeline)
(also, considered "evil")
- Results captured with a variable DO NOT enter a pipeline
$Foobar = ...(captured to variable, no Pipeline)$null = ...(no Pipleline)
(the same as... | Out-Null, but easier to read and much faster)
Example
function Get-LotsInThePipeline ($Thing1, $Thing2) {
Write-Output "a"
1
IF ($Thing) {
$null = Write-Output "b"
$null = 2
$Thing2
Return
}
Write-Output "c"
3
}
Get-LotsInThePipeline $true 'red'
Get-LotsInThePipeline $false 'blue'
There are two possible outputs for this program:
a, 1, "red"
a, 1, c, 3
When you need a limited set of pipeline values, you'll need to $null = xxxx...
a lot.
See https://stackoverflow.com/q/29556437/151312
2. Strict, Trace, & Verbose Modes
# set -e
$ErrorActionPreference = "Stop"
# set -x
Set-PSDebug -Trace 2
# DEBUG='true'
$VerbosePreference="Continue"
# if test -n "$DEBUG"; then echo "Debug 123"; fi
Write-Verbose "Debug: 123"
3. The Call Operator (&)
Normally you can run a command the same as a commandlet:
# Built-in Commandlet
Write-Host "Unpacking the tarball..."
# External Command
tar xvf foobar.tar.gz
However, if the command is any of:
- a script (particular that will change its parent's variables)
- accessed directly by it's path (i.e. it's not in
$Env:Path) - in a path with a space
you must use the call operator:
# can't write parent's variables
pwsh -ExecutionPolicy Bypass $HOME\.local\bin\_webi.ps1 xz
# can write parent's variables (same process)
& $HOME\.local\bin\_webi.ps1 xz
# not in PATH, and has space in its path
& ".\Foo Bar\foobar.exe" -baz
To use it with multiple arguments:
# this can be just the name, or the full path
$Cmd = 'curl.exe'
# mind the leading ,
$CmdArguments = , '--fail-with-body', '-sS'
& $Cmd $CmdArguments -o example.html 'https://example.com'
As you can see, the array of options and arguments is flattened, which makes constructing commands with complex arrangements much easier than... posix (but don't tell my friends I said that).
4. PowerShell's curl vs Windows' curl.exe
PowerShell has a built-in curl which is an alias for the Invoke-WebRequest
commandlet.
Never use curl. Always use curl.exe.
5. PowerShell Preferences and Policies
- Execution Policy must be set to allow PowerShell to run scripts:
# from a shell powershell -ExecutionPolicy Bypass .\foobar.ps1# for a script, itself Set-ExecutionPolicy Bypass -Scope Process & .\foobar.ps1 - Set Strict Mode (like
set -ein Bash, etc)$ErrorActionPreference = 'Stop' - Eliminate Progress Bars (they really slow Windows down) \
The number of progress created by
$ProgressPreference = 'SilentlyContinue'Invoke-WebRequestduring a download is so many that it literally can't download files over a few kilobytes in a reasonable amount of time unless this is turned off.