meta package for our recommended PowerShell plugins and settings
https://webinstall.dev/pwsh-essentials| Installer Source| Releases (json) (tab)
meta package for our recommended PowerShell plugins and settings
https://webinstall.dev/pwsh-essentials| Installer Source| Releases (json) (tab)
To update (replacing the current version) run webi pwsh-essentials
.
The tools you need to write PowerShell effectively.
This meta package will install the full set of plugins and settings we recommended.
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/
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.
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
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.
Return
keyword only serves to exit early.... | Write-Output
(the default)... | Write-Debug
... | Write-Verbose
... | Write-Information
... | Write-Warning
... | Write-Error
... | Write-Host
(forced console output, no Pipeline) $Foobar = ...
(captured to variable, no Pipeline)$null = ...
(no Pipleline) ... | Out-Null
, but easier to read and much faster)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
# 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"
&
)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:
$Env:Path
)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).
PowerShell has a built-in curl
which is an alias for the Invoke-WebRequest
commandlet.
Never use curl
. Always use curl.exe
.
# from a shell
powershell -ExecutionPolicy Bypass .\foobar.ps1
# for a script, itself
Set-ExecutionPolicy Bypass -Scope Process
& .\foobar.ps1
set -e
in Bash, etc)$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
The number of progress created by Invoke-WebRequest
during 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.