OReilly - Windows PowerShell Cookbook 3rd Edition - Lee Holmes - ISBN 1449320686

Link 1: Index of /computer/Windows
Link 2: Windows PowerShell Cookbook [pdf]

Supply Default Values for Parameters
PowerShell version 3 introduces the PSDefaultParameterValues preference variable. This preference variable is a hashtable.
$PSDefaultParameterValues["Get-Process:ID"] = $pid
Get-Process

Keys in the PSDefaultParameterValues hashtable must match the pattern cmdlet:parameter - that is, a cmdlet name and parameter name, separated by a colon. For example, the Send-MailMessage cmdlet looks for the $PSEmailServer variable if you do not supply a value for its -SmtpServer parameter.

[Console]::Beep(100,100) - Console.Beep Method
# generate a list of all cmdlets and aliases (along with their brief synopses)
Get-Help * -Category Cmdlet | Select-Object Name,Synopsis | Format-Table -Auto

#  Converting PowerShell commands into a Base64-encoded form  (54)
$commands = '1..3 | % { "PowerShell Command" }'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($commands)
$encodedString = [Convert]::ToBase64String($bytes)
# Once you have the encoded string, you can use it as the value of the EncodedCommand parameter
# Launching PowerShell with an encoded command from cmd.exe
C:\Temp>PowerShell -EncodedCommand MQAuAC4AMQAwACAAfAAgACUAIAB7ACAAIgBQAG8A
dwBlAHIAUwBoAGUAbABsACAAUgBvAGMAawBzACIAIAB9AA==

Learn Aliases for Common Parameters - Get-ParameterAlias.ps1 - Tokenizer API
If you want to see the aliases for a specific command, you can access its Parameters collection
(Get-Command New-TimeSpan).Parameters.Values | Select Name,Aliases

Search (formatted) command output for a pattern
Get-Service | Out-String -Stream | Select-String <search text> OR Get-Service | oss | sls <text>

Interactively View and Explore Objects - Show-Object - Abstract Syntax Tree (AST)
Automatic Variables - $pid
PS > $ps = { Get-Process -ID $pid }.Ast
PS > Show-Object.ps1 $ps

Redirecting output of a command into a file - A16 Capturing output
Get-Content .\infile.txt | Out-File -Encoding ascii -Width 100 -Append outfile.txt

Record a Transcript of Your Shell Session - places file in My Documents
Start-Transcript .... Stop-Transcript

When you install a module on your own system, the most common place to put it is in the WindowsPowerShell\Modules directory in your My Documents directory. To have PowerShell look in another directory for modules, add it to your personal PSModule Path environment variable.

Pipeline Examples - In the script block, the $_ (or $PSItem) variable represents the current input object.
Get-Process | Where-Object { $_.Name -like "*Search*" }
Get-Process | Where-Object { -not $_.Responding }
Get-Service | Where-Object { $_.Status -eq "Stopped" }
Get-Process | Where-Object Name -like "*Search*"

Group and Pivot Data by Name (91) - $processes = Get-Process | Group-Object -AsHash Id

Foreach-Object - In addition to the script block supported by the Foreach-Object cmdlet to process each element of the pipeline, it also supports script blocks to be executed at the beginning and end of the pipeline. 
$myArray = 1,2,3,4,5
$myArray | Foreach-Object -Begin {$sum = 0 } -Process { $sum += $_ } -End { $sum }
$myArray | Foreach-Object { $sum = 0 } { $sum += $_ } { $sum }

Output formatting - 4 cmdlets -  Format-Table, Format-List, Format-Wide and Format-Custom
By default, PowerShell takes the list of properties to display from the *.format.ps1xml files in PowerShell’s installation directory. In many situations, you’ll only get a small set of the properties.

PowerShell automatically defines several variables that represent things such as the location of your profile file, the process ID of 
PowerShell, and more. For a full list of these automatic variables, type Get-Help about_automatic_variables.
$fields = "Name",@{Label = "WS (MB)"; Expression = {$_.WS / 1mb}; Align = "Right"}
Get-Process | Format-Table $fields -Auto
ls | select Name,@{Name="Size (MB)"; Expression={"{0,8:0.00}" -f ($_.Length / 1MB)}}

Access Environment Variables - list all - Get-ChildItem env:
Get-ChildItem env:username OR Get-ChildItem Environment::username 

Control Access and Scope of Variables - Get-Help About_Scope

Work with .NET Objects - Classes contain methods (which let you perform operations) and properties (which let
you access information) 
static method - [ClassName]::MethodName(parameter list) or [System.Diagnostics.Process]::GetProcessById(0)
[System.DateTime]::Now
instance method - $objectReference.MethodName(parameter list) or $process.WaitForExit()
$today = Get-Date -> $today.DayOfWeek
Selected .NET Classes and their uses (943) or .NET API Browser 

Scope of Variables (128) - common = Global, Script & Local; also see Variables (864)

Create an Instance of a .NET Object (138)
$generator = New-Object System.Random; $generator.NextDouble()
OR (New-Object Net.WebClient).DownloadString("http://live.com")
Add-Type -Assembly System.Windows.Forms

$image = New-Object System.Drawing.Bitmap source.gif
$image.Save("source_converted.jpg", "JPEG")

Create Instances of Generic Objects
$coll = New-Object System.Collections.ObjectModel.Collection[Int]
$coll.Add(15)    << with only integer number or multiparameter below
$map = New-Object "System.Collections.Generic.Dictionary[String,Int]"
$map.Add("Test", 15)

Reduce Typing for Long Class Names - static methods, multiple objects & statis methods with mupltile types
$math = [System.Math]; $math::Min(1,10)
$namespace = "System.Collections.{0}"; $arrayList = New-Object ($namespace -f "ArrayList")
$namespace = "System.Diagnostics.{0}"; ([Type] ($namespace -f "EventLog"))::GetEventLogs()

Use a COM ObjectSelected COM Objects and Their Uses (959)
$sapi = New-Object -Com Sapi.SpVoice
$sapi.Speak("Hello World")

Create and Initialize Custom Objects, Add Custom Methods and Properties to Types,
Define Custom Formatting for a TypeUsing Conditional Statements,
Conditional Statements with Switches (Operating System SKU),
Operations with Loops, Looping StatementsRunning a loop at a constant speed 
 
$temperature = 25
if ($temperature -le 0) {"Freezing"}
elseif ($temperature -le 10) { "Cold" }
else {"Hot"}
$result = if (Get-Process -Name notepad) { "Running" } else { "Not running" }
$temperature = 20
switch ($temperature)
{ { $_ -lt 32 } { "Below Freezing"; break }
               32    { "Exactly Freezing"; break }
   { $_ -le 70} { "Warm"; break }
default           { "Hot" } }
for ($counter = 1; $counter -le 10; $counter++) { "Loop number $counter" }
foreach ($file in dir) { "File length: " + $file.Length }
1..10 | foreach { "Working" }
Get-ChildItem | Foreach-Object { "File length: " + $_.Length }
while ($response -ne "QUIT") { $response = Read-Host "Type something" }
do { $response = Read-Host "Type something" } while ($response -ne "QUIT")
do { $response = Read-Host "Type something" } until ($response -eq "QUIT")
"a","b","c" | Foreach-Object `
-Begin { "Starting"; $counter = 0 } `
-Process { "Processing $_"; $counter++ } `
-End { "Finishing: $counter" }

#To pause until the user presses the Enter key, use the pause command :
pause
# To pause until the user presses any key, use the ReadKey() method on the $host object:
$host.UI.RawUI.ReadKey()
# To pause a script for a given amount of time, use the Start-Sleep cmdlet: Start-Sleep 5
Start-Sleep -Milliseconds 300

Strings - Literal ($str='Hello') and Expanding strings ($str="Hello") or single and double quotes
Place Special Characters in a String, Insert Dynamic Information in a String,
Prevent a String from Including Dynamic Information, Place Formatted Information in a String,
Search a String for Text or a Pattern, Replace Text in a String,
Split a String on Text or a Pattern, Combine (join) Strings into a Larger String,
Convert a String to Uppercase or Lowercase, Trim a String,
Format a Date for Output, Convert Text Streams to Objects,
Generate Large Reports and Text Streams, Generate Source Code and Other Repetitive Text
$myString = 'hello `t $ENV:SystemRoot'
$myString = "hello `t $ENV:SystemRoot"
"Hello ""There""!" #result is: Hello "There"!
'Hello ''There''!' #result is: Hello 'There'!
$version = "Current PowerShell version is: $($PSVersionTable.PSVersion.Major)"
# Here strings may be of either the literal (single-quoted) or expanding (double-quoted) variety
$myHereString = @"
This text may span multiple lines, and may
contain "quotes."
"@
$header = "Report for Today"
$myString = "$header`n$('-' * $header.Length)" #make a line of dashes $header.Length long
# same result but using formatting operator which uses same rules as .NET string formatting
$myString = "{0}`n{1}" -f $header,('-' * $header.Length)
$formatString = "{0,8:D4} {1:C}`n"
$formatString -f 50,2.5677
# 1st number ({0}) is right-aligned qty in a box of eight characters (,8). It is formatted as a decimal number with four digits (:D4).
# 2nd number ({1}) represents the price, which formatted as currency (:C).
"$number2 divided by $number1 is " + $number2 / $number1
"{0} divided by {1} is {2}" -f $number2, $number1, ($number2 / $number1)

PowerShell’s formatting - Simple Operators, Detailed list of the formatting rules (933)
String.Format Method (MS docs), Standard Numeric Format Strings (MS Docs)

Search a string for Text or a Pattern
- like operator > "Hello World" -like "*llo W*" >> True
- match operator > "Hello World" -match '.*l[l-z]o W.*$'   >> True
- Contains() method > "Hello World".Contains("World")   >> True
- IndexOf() method to determine location of 1 string within another > "Hello World".IndexOf("World")   >> 6

A common use of regular expressions is to search for a string that spans multiple lines. By default, regular expressions do not search across lines, but you can use the singleline (?s) option to instruct them to do so:
PS > "Hello `n World" -match "Hello.*World" >> False
PS > "Hello `n World" -match "(?s)Hello.*World" >> True
Regular Expression Reference

Replace string & Split string - see Split a String on Text or a Pattern
"Hello World".Replace("World", "PowerShell")  >> Hello PowerShell
"Hello World" -replace '(.*) (.*)','$2 $1'  >> World Hello
"Power[Shell]" -replace "[Shell]","ful"  >> Powfulr[fulfulfulfulful]
# In regular expressions, square brackets around a set of characters means “match any of the characters inside of the square brackets.” In our example, this translates to “Replace the characters S, h, e, and l with ‘ful’.”
"Power[Shell]" -replace "\[Shell\]","ful"  >> Powerful
"Power[Shell]" -replace ([Regex]::Escape("[Shell]")),"ful"  >> Powerful
# Capitalize the first character (\w) after a word boundary (\b)
[Regex]::Replace("hello world", '\b(\w)', { $args[0].Value.ToUpper() })  >> Hello World
"a.b.c" -split '.',0,"SimpleMatch"   PS > "1234567890" -split { ($_ % 2) -eq 0 }
("A","B","C") -join "`r`n"
Use-Culture en-GB { "quit".ToUpper() } # localisation language
#generate source code or other repetitive text
$process.PsObject.Properties | % { 'Console.WriteLine("{0}: " + process.{0});' -f $_.Name }


Calculations and Math
Perform Simple Arithmetic, Perform Complex Arithmetic, Measure Statistical Properties of a List
Work with Numbers as Binary, Simplify Math with Administrative ConstantsConvert Numbers Between Bases 
[math] | Get-Member -Static # -MemberType method
0..7 | % {write-host $_ ([math]::pow(2,$_)) }
function Convert-RadiansToDegrees($angle) { $angle / (2 * [Math]::Pi) * 360 }
function Convert-DegreesToRadians($angle) { $angle / 360 * (2 * [Math]::Pi) }
[BigInt] "9628546546..." #otherwise PowerShell will truncate to 9.628E+38 
[System.Numerics.Complex]::ImaginaryOne * [System.Numerics.Complex]::ImaginaryOne | fl
Get-ChildItem | Measure-Object -Property Length -Max -Min -Average -Sum
$times = dir | Foreach-Object { $_.LastWriteTime } ## Measure the average Ticks property of those LastWriteTime
$results = $times | Measure-Object Ticks -Average ## Create a new DateTime out of the average Ticks
New-Object DateTime $results.Average  ## Sunday, June 11, 2006 6:45:01 AM
$hexNumber = 0x1234 #prefix hexadeximal numbers with 0x
[Convert]::ToString(1234, 2) #or convert from binary [Convert]::ToInt32("10011010010", 2)
[Convert]::ToString(1234, 16) # or use formatting operator "{0:X4}" -f 1234
# Enumerations
[Enum]::GetNames([System.IO.FileAttributes])
[enum]::GetNames([ConsoleColor]) | % { $num = [ConsoleColor]::$_.Value__; Write-Host "$num - $_" -ForegroundColor $num }

Lists, Arrays, and Hashtables - Arrays and Lists, Hashtables (Associative Arrays)
Create an Array or List of Items, Create a Jagged or Multidimensional ArrayAccess Elements of an Array
Visit Each Element of an Array, Sort an Array or List of ItemsDetermine Whether an Array Contains an Item
Combine Two Arrays, Find Items in an Array That Match a ValueCompare Two Lists
Remove Elements from an Array, Find Items in an Array Greater or Less Than a ValueUse the ArrayList Class for Advanced Array Tasks 
Create a Hashtable or Associative ArraySort a Hashtable by Key or Value 
$myArray = 1,2,"Hello World" # specific size $myArray = New-Object string[] 10
$list = New-Object Collections.Generic.List[Int] # $list.Add(10) specific type strongly typed collection 
# frequently modified array - create ArrayList
$myArray = New-Object System.Collections.ArrayList
# cast [void] to supress sending data to output pipeline
[void] $myArray.Add("Hello") # $myArray.RemoveAt(1)
[void] $myArray.AddRange( ("World","How","Are","You") )
$myArray = @(Get-Process Explorer) # treat command output as a list
$myArray = 1,2,"Hello World" # $myArray[1..2 + 0] << array ranges & slicing
# different ways to visit each array element $myArray = 1,2,3
$myArray | Foreach-Object { $sum += $_ }
foreach($element in $myArray) { $sum += $element }
for($counter = 0; $counter -lt $myArray.Count; $counter++) {$sum += $myArray[$counter]}
Get-ChildItem | Sort-Object -Descending Length | Select Name,Length
"Hello","World","And","PowerShell" | Sort-Object { $_.Substring(1,1) }
$list = "Hello","World","And","PowerShell"; $list = $list | Sort-Object; [Array]::Sort($list)
$myHashtable = @{ Key1 = "Value1"; "Key 2" = 1,2,3 }; $myHashtable["New Item"] = 5
$myHashtable = @{}; $myHashtable["Hello"] = "World"; $myHashtable.AnotherHello = "AnotherWorld"
# sort unordered hashtable/list
$myHashtable.GetEnumerator() | Sort Name # or value $myHashtable.GetEnumerator() | Sort Value
$myHashtable = [Ordered] @{Duck = 1;Ali = 2;Hectic = 11;Alien = 4;} #retains order in which added items

Utility Tasks
Get the System Date and Time, Measure the Duration of a CommandRead and Write from the Windows Clipboard
Generate a Random Number or Object, Program: Search the Windows Start MenuProgram: Show Colorized Script Content
$date = Get-Date; $date.DayOfWeek
Measure-Command { Start-Sleep -Milliseconds 337 }; Get-Random -Minimum 1 -Maximum 21
$suits = "Hearts","Clubs","Spades","Diamonds"
$faces = (2..10)+"A","J","Q","K"
$cards = foreach($suit in $suits) {foreach($face in $faces) { "$face of $suit" } }
$cards | Get-Random # A of Spades, 2 of Clubs, ... etc.
1..10 | % { (New-Object System.Random).Next(1, 21) } # OR 1..10 | & { Get-Random -Min 1 -Max 21 }


---------------------------------------------------------------------
Common Tasks
Simple Files
Get the Content of a File, Search a File for Text or a PatternParse and Manage Text-Based Logfiles
Parse and Manage Binary Files, Create a Temporary File, Search and Replace Text in a File
# 3 ways to read text file
$content = Get-Content c:\temp\file.txt
$content = ${c:\temp\file.txt} # get-content variable syntax
$content = Get-Content c:\temp\file.txt -Raw
$contentLines = [System.IO.File]::ReadAllLines("c:\temp\file.txt")
# If you want split the content based on a string rather than default newlines), use the Get-Content cmdlet’s -Delimiter parameter
Select-String -Simple SearchText file.txt # or Select-String "\(...\) ...-...." phone.txt
Get-ChildItem *.txt -Recurse | Select-String pattern #or dir *.txt -rec | sls pattern 
$matches = Select-String "output file" transcript.txt; $matches | Select LineNumber,Line
Select-String "\(...\) ...-...." phone.txt | Select -Expand Matches
Select-String "\((...)\) ...-...." phone.txt | Select -Expand Matches | Foreach { $_.Groups[1] }
Get-ChildItem | Where { $_ | Select-String "Debug" -Quiet }
# parsing log files
$records = gc AddressBook.txt -Delimiter "----"
$parseExpression = "(?s)Name: (\S*).*Phone: (\S*).*"
$records | Convert-TextObject -ParseExpression $parseExpression
$filename = [System.IO.Path]::GetTempFileName()
$newname = [System.IO.Path]::ChangeExtension($filename, ".cs")
Move-Item $filename $newname # optionally rename temp file
# (... use the file ...) create temp file managed by .NET Framework
Remove-Item -Force $filename
$filename = "file.txt" #replace text in file
$match = "source text"; $replacement = "replacement text"
$content = Get-Content $filename
$content = $content -creplace $match,$replacement
$content -replace '(.*) (.*)','$2, $1' # swapping two strings using RegEx (Regular Expression)
$content | Set-Content $filename



.