Payette's Windows Powershell in Action: the only true powershell documentation

This isn’t really a question. But it seems to me there’s a disconnect between Bruce Payette’s book and the official documentation. I had no idea I could do all this stuff. I guess some are in the docs, but are not done commonly. Although I would never use ‘>’ and ‘>>’, since they encode in unicode.

# where method (and foreach method) which are faster
(Get-Process | sort Handles).where({$_.Handles -gt 1000}, 'Until')
(Get-Process notepad).foreach('Kill')

# hide output with [void]
[void] $(Write-Output "discard me")

# invoke a method with a variable
$method = 'sin'

# swap two variables:
$a,$b = $b,$a

# reference any psdrive like C: with a variable, but need the curly braces {} 
# (but how do I pass in "$path = 'file.txt'?)
# and search and replace a file
${c:file.txt} = ${c:file.txt} -replace 'oldstring','newstring'

# and swap two files
${c:file1.txt},${c:file2.txt} = ${c:file2.txt},${c:file1.txt}

# $foreach and movenext, ok this is in the doc but I didn't know it
foreach ($i in 1..10)
{ [void] $foreach.MoveNext(); $i + $foreach.Current }

# foreach-object operation statement, in docs but didn't know
ps | foreach-object name
'hi.there' | Foreach-object Split .

# using assemply (didn't know using namespace)
using assembly System.Windows.Forms
using namespace System.Windows.Forms
[messagebox]::show('hello world')

# an assignment is an expression
if (2 -eq ($a = 2)) { 'yes' }

# and then with redirection save output and error to separate variables
$err = $( $output = ls foo3 ) 2>&1

# restrict var to int, in doc but didn't know
[int]$a = 1

# restrict length of var like in advanced functions
[ValidateLength(0,5)] [string] $cv = ''

# subexpressions $() aren't just for double quoted strings, 
# you can put in multiple statements with semicolons and keywords like if and foreach
# and put them anywhere you can put an expression or pipeline
$( echo hi; echo there ) | measure
if ( $(if (1 -eq 1) {'yes'}) -eq 'yes' ) { 'yep' }
for ($i=0; $($y = $i*2; $i -lt 5); $i++) { $y }

# labels, in doc but didn't know
# loop label, break out of both loops
$target = 'outer'
:outer while (1) {
  while(1) {
    break $target

# switch, so many things, arrays and $_, in doc but didn't know
switch(1,2,3,4,5,6) {
  {$_ % 2} {"Odd $_"; continue}
  4 {'FOUR'}
  default {"Even $_"}

# $switch and movenext and current
switch ($options){
  '-a' { $a=$true }
  '-b' { [void] $switch.MoveNext(); $b= $switch.Current }
  '-c' { $c=$true }
  '-d' { $d=$true }

# three script blocks with foreach-object -process arg (for begin, process, end)
gps svchost | foreach-object {$t=0} {$t+=$_.handles} {$t}

# -replace has a lot of codes for the 2nd arg, 
# doc is in some regex doc that's not linked from the about comparison operators page
$number Substitutes the last submatch matched by group number.
${name} Substitutes the last submatch matched by a named capture of the form (?<name>).
$$ Substitutes a single "$" literal.
$& Substitutes a copy of the entire match itself.
$` Substitutes all the text from the argument string before the matching portion.
$' Substitutes all the text of the argument string after the matching portion.
$+ Substitutes the last submatch captured.
$_ Substitutes the entire argument string.

# pipes in simple funcs ($input has a .movenext() too)
function sum {
  foreach ($n in $input) { $total += $n }
1,2,3 | sum

yes, that book is the real bible…

better to make above all as a blog post or in github as markdown with a nice title, let the unknown know it.

Where in github?

In your’s, if you have github account. Let other’s correct/contribute.

Haven’t read the book but I don’t think it’s that common that people know that you can create “anonymous” functions.


if the leftover is 1 it’s and odd number, else it’s even.

$oddOrEven = {param($a) if($a % 2){“Odd”}else{“Even”}}

call the anonymous function

&$oddOrEven 5

Thanks. I haven’t gotten to the metaprogramming chapter yet.

Oh, get-content and set-content work with all providers. Here it is with variables.

PS /Users/js> get-content variable:a | set-content -value 'there'
PS /Users/js> $a

Too bad you can’t use scriptblock paramters with -value since it’s an object. (The path is being piped in as PSPath.)

PS /Users/js> get-content variable:a | set-content -value {$_ -replace 'there','hi'} 
PS /Users/js> $a
 $_ -replace 'there','hi' 

do you know the stream technique

Mathias showed me this first…

Set-Content -Path c:\temp\test.txt -Value YouCanSeeMe
Set-Content -Path c:\temp\test.txt -Value YouCannotSeeMe -Stream foo
Notepad c:\temp\test.txt
Get-Content -Path c:\temp\test.txt
Get-Content -Path c:\temp\test.txt -Stream foo

I have and used every version of this book since he released it.

It’s the default advanced PowerShell book on the market and the one I specifically recommend.

These should be on every PowerSheller’s desk or in electronic form on their devices.

Beginning ---

Learn Windows PowerShell in a Month of Lunches 3rd Edition
Donald W. Jones (Author),‎ Jeffrey Hicks (Author)
ISBN-13: 978-1617294167
ISBN-10: 1617294160

Internediate —

Windows PowerShell Cookbook: The Complete Guide to Scripting Microsoft’s Command Shell 3rd Edition
Lee Holmes (Author)
ISBN-13: 978-1449320683
ISBN-10: 1449320686

Advanced —

Windows PowerShell in Action 3rd Edition
by Bruce Payette (Author),‎ Richard Siddaway (Author)
ISBN-13: 978-1633430297
ISBN-10: 1633430294

Get and set a variable in a module scope with the call operator (undocumented):

# get module object
$m = get-module counter

& $m Get-Variable count
& $m Set-Variable count 33

# see func def
& $m Get-Item function:Get-Count

# run with commandinfo object and call operator
$d = get-command get-date
& $d

# set function to scriptblock
${function:Set-CountIncrement} = $setIncrement

# scriptblock process block (there are scriptblock begin and end blocks too)
1..5 | &{process{$_ * 2}}