Final look-over and adjusting carriage returns

Reducing line length
Adjusting grammar
Fixing some inconsistencies in variables and properties
This commit is contained in:
Andrew Ryan Davis 2020-08-20 12:12:01 -07:00
parent 88f7de0db0
commit b46242c138

View File

@ -43,9 +43,10 @@ Powershell as a Language:
10 * 2 # => 20 10 * 2 # => 20
35 / 5 # => 7.0 35 / 5 # => 7.0
# Powershell uses banker's rounding # Powershell uses banker's rounding,
# Meaning [int]1.5 would round to 2 but so would [int]2.5 # meaning [int]1.5 would round to 2 but so would [int]2.5
# division always returns a float. You must cast result to [int] to round # Division always returns a float.
# You must cast result to [int] to round.
[int]5 / [int]3 # => 1.66666666666667 [int]5 / [int]3 # => 1.66666666666667
[int]-5 / [int]3 # => -1.66666666666667 [int]-5 / [int]3 # => -1.66666666666667
5.0 / 3.0 # => 1.66666666666667 5.0 / 3.0 # => 1.66666666666667
@ -55,10 +56,10 @@ Powershell as a Language:
# Modulo operation # Modulo operation
7 % 3 # => 1 7 % 3 # => 1
# Exponentiation requires longform or the built-in [Math] class # Exponentiation requires longform or the built-in [Math] class.
[Math]::Pow(2,3) # => 8 [Math]::Pow(2,3) # => 8
# Enforce order of operations with parentheses # Enforce order of operations with parentheses.
1 + 3 * 2 # => 7 1 + 3 * 2 # => 7
(1 + 3) * 2 # => 8 (1 + 3) * 2 # => 8
@ -75,20 +76,20 @@ $False # => False
$True -and $False # => False $True -and $False # => False
$False -or $True # => True $False -or $True # => True
# True and False are actually 1 and 0 but only support limited arithmetic # True and False are actually 1 and 0 but only support limited arithmetic.
# However, casting the bool to int resolves this # However, casting the bool to int resolves this.
$True + $True # => 2 $True + $True # => 2
$True * 8 # => '[System.Boolean] * [System.Int32]' is undefined $True * 8 # => '[System.Boolean] * [System.Int32]' is undefined
[int]$True * 8 # => 8 [int]$True * 8 # => 8
$False - 5 # => -5 $False - 5 # => -5
# Comparison operators look at the numerical value of True and False # Comparison operators look at the numerical value of True and False.
0 -eq $False # => True 0 -eq $False # => True
1 -eq $True # => True 1 -eq $True # => True
2 -eq $True # => False 2 -eq $True # => False
-5 -ne $False # => True -5 -ne $False # => True
# Using boolean logical operators on ints casts them to booleans for evaluation # Using boolean logical operators on ints casts to booleans for evaluation.
# but their non-cast value is returned # but their non-cast value is returned
# Don't mix up with bool(ints) and bitwise -band/-bor # Don't mix up with bool(ints) and bitwise -band/-bor
[bool](0) # => False [bool](0) # => False
@ -115,10 +116,10 @@ $False - 5 # => -5
1 -lt 2 -and 2 -lt 3 # => True 1 -lt 2 -and 2 -lt 3 # => True
2 -lt 3 -and 3 -lt 2 # => False 2 -lt 3 -and 3 -lt 2 # => False
# (-is vs. -eq) -is checks if two objects are the same type # (-is vs. -eq) -is checks if two objects are the same type.
# -eq checks if the objects have the same values. # -eq checks if the objects have the same values.
# Note: we called '[Math]' from .NET previously without the preceeding # Note: we called '[Math]' from .NET previously without the preceeding
# namespaces. We can do the same with [Collections.ArrayList] if preferred # namespaces. We can do the same with [Collections.ArrayList] if preferred.
[System.Collections.ArrayList]$a = @() # Point a at a new list [System.Collections.ArrayList]$a = @() # Point a at a new list
$a = (1,2,3,4) $a = (1,2,3,4)
$b = $a # => Point b at what a is pointing to $b = $a # => Point b at what a is pointing to
@ -142,12 +143,15 @@ $b -is $a.GetType() # => False, a and b types not equal
# You can find the length of a string # You can find the length of a string
("This is a string").Length # => 16 ("This is a string").Length # => 16
# You can also format using f-strings or formatted string literals # You can also format using f-strings or formatted string literals.
$name = "Steve" $name = "Steve"
$age = 22 $age = 22
"He said his name is $name." # => "He said his name is Steve" "He said his name is $name."
"{0} said he is {1} years old." -f $name, $age # => "Steve said he is 22 years old" # => "He said his name is Steve"
"$name's name is $($name.Length) characters long." # => "Steve's name is 5 characters long." "{0} said he is {1} years old." -f $name, $age
# => "Steve said he is 22 years old"
"$name's name is $($name.Length) characters long."
# => "Steve's name is 5 characters long."
# Escape Characters in Powershell # Escape Characters in Powershell
# Many languages use the '\', but Windows uses this character for # Many languages use the '\', but Windows uses this character for
@ -166,7 +170,7 @@ $null # => None
# $null, 0, and empty strings and arrays all evaluate to False. # $null, 0, and empty strings and arrays all evaluate to False.
# All other values are True # All other values are True
function test ($value) { function Test-Value ($value) {
if ($value) { if ($value) {
Write-Output 'True' Write-Output 'True'
} }
@ -175,12 +179,13 @@ function test ($value) {
} }
} }
test ($null) # => False Test-Value ($null) # => False
test (0) # => False Test-Value (0) # => False
test ("") # => False Test-Value ("") # => False
test [] # => True *[] calls .NET classes; creates '[]' string when passed to func Test-Value [] # => True
test ({}) # => True # *[] calls .NET class; creates '[]' string when passed to function
test @() # => False Test-Value ({}) # => True
Test-Value @() # => False
#################################################### ####################################################
@ -205,9 +210,9 @@ $someVariable # => 5
0 ? 'yes' : 'no' # => no 0 ? 'yes' : 'no' # => no
# The default array object in Powershell is an fixed length array # The default array object in Powershell is an fixed length array.
$defaultArray = "thing","thing2","thing3" $defaultArray = "thing","thing2","thing3"
# you can add objects with '+=', but cannot remove objects # you can add objects with '+=', but cannot remove objects.
$defaultArray.Add("thing4") # => Exception "Collection was of a fixed size." $defaultArray.Add("thing4") # => Exception "Collection was of a fixed size."
# To have a more workable array, you'll want the .NET [ArrayList] class # To have a more workable array, you'll want the .NET [ArrayList] class
# It is also worth noting that ArrayLists are significantly faster # It is also worth noting that ArrayLists are significantly faster
@ -217,12 +222,12 @@ $defaultArray.Add("thing4") # => Exception "Collection was of a fixed size."
# You can start with a prefilled ArrayList # You can start with a prefilled ArrayList
[System.Collections.ArrayList]$otherArray = @(4, 5, 6) [System.Collections.ArrayList]$otherArray = @(4, 5, 6)
# Add stuff to the end of a list with add (Note: it produces output, so append to $null) # Add to the end of a list with 'Add' (Note: produces output, append to $null)
$array.add(1) > $null # $array is now [1] $array.Add(1) > $null # $array is now [1]
$array.add(2) > $null # $array is now [1, 2] $array.Add(2) > $null # $array is now [1, 2]
$array.add(4) > $null # $array is now [1, 2, 4] $array.Add(4) > $null # $array is now [1, 2, 4]
$array.add(3) > $null # $array is now [1, 2, 4, 3] $array.Add(3) > $null # $array is now [1, 2, 4, 3]
# Remove from the end with index of count of objects-1 as arrays are indexed starting 0 # Remove from end with index of count of objects-1; array index starts at 0
$array.RemoveAt($array.Count-1) # => 3 and array is now [1, 2, 4] $array.RemoveAt($array.Count-1) # => 3 and array is now [1, 2, 4]
# Let's put it back # Let's put it back
$array.Add(3) > $null # array is now [1, 2, 4, 3] again. $array.Add(3) > $null # array is now [1, 2, 4, 3] again.
@ -265,24 +270,24 @@ $array.AddRange($otherArray) # Now $array is [1, 2, 3, 4, 5, 6]
# Check for existence in a array with "in" # Check for existence in a array with "in"
1 -in $array # => True 1 -in $array # => True
# Examine the length with "Count" (Note: Length method on arrayList = each items length) # Examine length with "Count" (Note: "Length" on arrayList = each items length)
$array.Count # => 6 $array.Count # => 6
# Tuples are like arrays but are immutable. # Tuples are like arrays but are immutable.
# To use Tuples in powershell, you must use the .NET tuple class # To use Tuples in powershell, you must use the .NET tuple class.
$tuple = [System.Tuple]::Create(1, 2, 3) $tuple = [System.Tuple]::Create(1, 2, 3)
$tuple.Item(0) # => 1 $tuple.Item(0) # => 1
$tuple.Item(0) = 3 # Raises a TypeError $tuple.Item(0) = 3 # Raises a TypeError
# You can do some of the array methods on tuples, but they are limited # You can do some of the array methods on tuples, but they are limited.
$tuple.Length # => 3 $tuple.Length # => 3
$tuple + (4, 5, 6) # => Exception $tuple + (4, 5, 6) # => Exception
$tuple[0..2] # => $null $tuple[0..2] # => $null
2 -in $tuple # => False 2 -in $tuple # => False
# Hashtables store mappings from keys to values, similar to Dictionaries # Hashtables store mappings from keys to values, similar to Dictionaries.
$emptyHash = @{} $emptyHash = @{}
# Here is a prefilled dictionary # Here is a prefilled dictionary
$filledHash = @{"one"= 1 $filledHash = @{"one"= 1
@ -294,10 +299,10 @@ $filledHash["one"] # => 1
# Get all keys as an iterable with ".Keys". # Get all keys as an iterable with ".Keys".
# items maintain the order at which they are inserted into the dictionary. # items maintain the order at which they are inserted into the dictionary.
$filledHash.keys # => ["one", "two", "three"] $filledHash.Keys # => ["one", "two", "three"]
# Get all values as an iterable with ".Values". # Get all values as an iterable with ".Values".
$filledHash.values # => [1, 2, 3] $filledHash.Values # => [1, 2, 3]
# Check for existence of keys or values in a hash with "-in" # Check for existence of keys or values in a hash with "-in"
"one" -in $filledHash.Keys # => True "one" -in $filledHash.Keys # => True
@ -309,7 +314,7 @@ $filledHash["four"] # $null
# Adding to a dictionary # Adding to a dictionary
$filledHash.Add("five",5) # $filledHash["five"] is set to 5 $filledHash.Add("five",5) # $filledHash["five"] is set to 5
$filledHash.Add("five",6) # exception "Item with key "five" has already been added" $filledHash.Add("five",6) # exception "Item with key "five" has already been added"
$filledHash["four"] = 4 # $filledHash["four"] is set to 4, run again and it does nothing $filledHash["four"] = 4 # $filledHash["four"] is set to 4, running again does nothing
# Remove keys from a dictionary with del # Remove keys from a dictionary with del
$filledHash.Remove("one") # Removes the key "one" from filled dict $filledHash.Remove("one") # Removes the key "one" from filled dict
@ -428,8 +433,8 @@ Add-Numbers 1 2 # => 3
# Calling functions with parameters # Calling functions with parameters
function Add-ParamNumbers { function Add-ParamNumbers {
param( [int]$FirstNumber, [int]$SecondNumber ) param( [int]$firstNumber, [int]$secondNumber )
$FirstNumber + $SecondNumber $firstNumber + $secondNumber
} }
Add-ParamNumbers -FirstNumber 1 -SecondNumber 2 # => 3 Add-ParamNumbers -FirstNumber 1 -SecondNumber 2 # => 3
@ -457,9 +462,9 @@ function New-Website() {
[ValidateSet(3000,5000,8000)] [ValidateSet(3000,5000,8000)]
[int]$port = 3000 [int]$port = 3000
) )
BEGIN { Write-Verbose 'Creating new website(s)' } BEGIN { Write-Output 'Creating new website(s)' }
PROCESS { Write-Output "name: $siteName, port: $port" } PROCESS { Write-Output "name: $siteName, port: $port" }
END { Write-Verbose 'Website(s) created' } END { Write-Output 'Website(s) created' }
} }
@ -521,8 +526,8 @@ String Instrument Plucked String
## 6.1 Inheritance ## 6.1 Inheritance
#################################################### ####################################################
# Inheritance allows new child classes to be defined that inherit methods and # Inheritance allows new child classes to be defined that inherit
# variables from their parent class. # methods and variables from their parent class.
class Guitar : Instrument class Guitar : Instrument
{ {
@ -551,67 +556,68 @@ True False Guitar Instrument
## 7. Advanced ## 7. Advanced
#################################################### ####################################################
# The powershell pipeline allows things like High-Order Functions # The powershell pipeline allows things like High-Order Functions.
# Group Object is a handy command that does incredible things for us # Group-Object is a handy cmdlet that does incredible things.
# It works much like a GROUP BY in SQL would # It works much like a GROUP BY in SQL.
<# <#
The following will get all the running processes The following will get all the running processes,
Group them by Name group them by Name,
And tell us how many instances of each process we have running and tell us how many instances of each process we have running.
Tip: Chrome and svcHost are usually big numbers in this regard Tip: Chrome and svcHost are usually big numbers in this regard.
#> #>
Get-Process | Foreach-Object ProcessName | Group-Object Get-Process | Foreach-Object ProcessName | Group-Object
# Useful pipeline examples are iteration and filtering # Useful pipeline examples are iteration and filtering.
1..10 | ForEach-Object { "Loop number $PSITEM" } 1..10 | ForEach-Object { "Loop number $PSITEM" }
1..10 | Where-Object { $PSITEM -gt 5 } | ConvertTo-Json 1..10 | Where-Object { $PSITEM -gt 5 } | ConvertTo-Json
# A noteable pitfall of the pipeline is it's performance when # A notable pitfall of the pipeline is it's performance when
# compared with other options # compared with other options.
# Additionally, raw bytes are not passed through the pipeline # Additionally, raw bytes are not passed through the pipeline,
# so passing an image causes some issues # so passing an image causes some issues.
# See more on that in the link at the bottom # See more on that in the link at the bottom.
<# <#
Asynchronous functions exist in the form of jobs Asynchronous functions exist in the form of jobs.
Typically a procedural language Typically a procedural language,
Powershell can operate many non-blocking functions when invoked as Jobs Powershell can operate non-blocking functions when invoked as Jobs.
#> #>
# This function is commonly known to be non-optimized, and therefore slow # This function is known to be non-optimized, and therefore slow.
$installedApps = Get-CimInstance -ClassName Win32_Product $installedApps = Get-CimInstance -ClassName Win32_Product
# If we had a script, it would hang at this func for a period of time # If we had a script, it would hang at this func for a period of time.
$scriptBlock = {Get-CimInstance -ClassName Win32_Product} $scriptBlock = {Get-CimInstance -ClassName Win32_Product}
Start-Job -ScriptBlock $scriptBlock Start-Job -ScriptBlock $scriptBlock
# This will start a background job that runs the command # This will start a background job that runs the command.
# You can then obtain the status of jobs and their returned results # You can then obtain the status of jobs and their returned results.
$allJobs = Get-Job $allJobs = Get-Job
$JobResponse = Get-Job | Receive-Job $jobResponse = Get-Job | Receive-Job
# Math is built in to powershell and has many functions # Math is built in to powershell and has many functions.
$r=2 $r=2
$pi=[math]::pi $pi=[math]::pi
$r2=[math]::pow( $r, 2 ) $r2=[math]::pow( $r, 2 )
$Area = $pi*$r2 $area = $pi*$r2
$Area $area
# To see all possibilities, check the members # To see all possibilities, check the members.
[System.Math] | Get-Member -Static -MemberType All [System.Math] | Get-Member -Static -MemberType All
<# <#
This is a silly one This is a silly one:
You may one day be asked to create a func that could take $start and $end You may one day be asked to create a func that could take $start and $end
and reverse anything in an array within the given range and reverse anything in an array within the given range
based on an arbitrary array without mutating the original array based on an arbitrary array without mutating the original array.
Let's see one way to do that and introduce another data structure Let's see one way to do that and introduce another data structure.
#> #>
$targetArray = 'a','b','c','d','e','f','g','h','i','j','k','l','m','n' $targetArray = 'a','b','c','d','e','f','g','h','i','j','k','l','m'
function Format-Range ($start, $end) { function Format-Range ($start, $end) {
[System.Collections.ArrayList]$firstSectionArray = @() [System.Collections.ArrayList]$firstSectionArray = @()
@ -628,16 +634,16 @@ function Format-Range ($start, $end) {
$secondSectionArray.Add($targetArray[$index]) > $null $secondSectionArray.Add($targetArray[$index]) > $null
} }
} }
$returnArray = $firstSectionArray + $stack.ToArray() + $secondSectionArray $finalArray = $firstSectionArray + $stack.ToArray() + $secondSectionArray
Write-Output $returnArray Write-Output $finalArray
} }
Format-Range 2 6 # => 'a','b','g','f','e','d','c','h','i','j','k','l','m','n' Format-Range 2 6 # => 'a','b','g','f','e','d','c','h','i','j','k','l','m'
# The previous method works, but it uses extra memory by allocating new arrays # The previous method works, but uses extra memory by allocating new arrays.
# It's also kind of lengthy # It's also kind of lengthy.
# Let's see how we can do this without allocating a new array # Let's see how we can do this without allocating a new array.
# This is slightly faster as well # This is slightly faster as well.
function Format-Range ($start, $end) { function Format-Range ($start, $end) {
while ($start -lt $end) while ($start -lt $end)
@ -651,7 +657,7 @@ function Format-Range ($start, $end) {
return $targetArray return $targetArray
} }
Format-Range 2 6 # => 'a','b','g','f','e','d','c','h','i','j','k','l','m','n' Format-Range 2 6 # => 'a','b','g','f','e','d','c','h','i','j','k','l','m'
``` ```
Powershell as a Tool: Powershell as a Tool:
@ -688,22 +694,26 @@ $PSVersionTable
``` ```
```Powershell ```Powershell
# Calling external commands, executables, and functions with the call operator. # Calling external commands, executables,
# Executables with arguments passed create issues # and functions with the call operator.
# Exe paths with arguments passed or containing spaces can create issues.
C:\Program Files\dotnet\dotnet.exe C:\Program Files\dotnet\dotnet.exe
The term 'C:\Program' is not recognized as a name of a cmdlet, function, script file, or executable program. # The term 'C:\Program' is not recognized as a name of a cmdlet,
Check the spelling of the name, or if a path was included, verify that the path is correct and try again # function, script file, or executable program.
# Check the spelling of the name, or if a path was included,
# verify that the path is correct and try again
"C:\Program Files\dotnet\dotnet.exe" "C:\Program Files\dotnet\dotnet.exe"
C:\Program Files\dotnet\dotnet.exe # returns the string rather than execute it C:\Program Files\dotnet\dotnet.exe # returns string rather than execute
&"C:\Program Files\dotnet\dotnet.exe --help" # fail &"C:\Program Files\dotnet\dotnet.exe --help" # fail
&"C:\Program Files\dotnet\dotnet.exe" --help # success &"C:\Program Files\dotnet\dotnet.exe" --help # success
# Alternatively, you can use dot-sourcing here # Alternatively, you can use dot-sourcing here
."C:\Program Files\dotnet\dotnet.exe" --help # success ."C:\Program Files\dotnet\dotnet.exe" --help # success
# the call operator (&) is similar to Invoke-Expression, but IEX runs in current scope. # the call operator (&) is similar to Invoke-Expression,
# Standard usage of '&' would be to invoke a scriptblock inside of your script. # but IEX runs in current scope.
# One usage of '&' would be to invoke a scriptblock inside of your script.
# Notice the variables are scoped # Notice the variables are scoped
$i = 2 $i = 2
$scriptblock = { $i=5; Write-Output $i } $scriptblock = { $i=5; Write-Output $i }
@ -714,17 +724,17 @@ invoke-expression ' $i=5; Write-Output $i ' # => 5
$i # => 5 $i # => 5
# Alternatively, to preserve changes to public variables # Alternatively, to preserve changes to public variables
# you can use "Dot-Sourcing". This will run in the current scope # you can use "Dot-Sourcing". This will run in the current scope.
$x=1 $x=1
&{$x=2};$x # => 1 &{$x=2};$x # => 1
.{$x=2};$x # => 2 .{$x=2};$x # => 2
# Remoting into computers is easy # Remoting into computers is easy.
Enter-PSSession -ComputerName RemoteComputer Enter-PSSession -ComputerName RemoteComputer
# Once remoted in, you can run commands as if you're local # Once remoted in, you can run commands as if you're local.
RemoteComputer\PS> Get-Process powershell RemoteComputer\PS> Get-Process powershell
<# <#
@ -736,10 +746,10 @@ Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
RemoteComputer\PS> Exit-PSSession RemoteComputer\PS> Exit-PSSession
<# <#
Powershell is an incredible tool for Windows management and Automation Powershell is an incredible tool for Windows management and Automation.
Let's take the following scenario Let's take the following scenario:
You have 10 servers You have 10 servers.
You need to check whether a service is running on all of them You need to check whether a service is running on all of them.
You can RDP and log in, or PSSession to all of them, but why? You can RDP and log in, or PSSession to all of them, but why?
Check out the following Check out the following
#> #>
@ -757,24 +767,24 @@ $serverList = @(
'server10' 'server10'
) )
[scriptblock]$Script = { [scriptblock]$script = {
Get-Service -DisplayName 'Task Scheduler' Get-Service -DisplayName 'Task Scheduler'
} }
foreach ($server in $serverList) { foreach ($server in $serverList) {
$CmdSplat = @{ $cmdSplat = @{
ComputerName = $Server ComputerName = $server
JobName = 'checkService' JobName = 'checkService'
ScriptBlock = $Script ScriptBlock = $script
AsJob = $true AsJob = $true
ErrorAction = 'SilentlyContinue' ErrorAction = 'SilentlyContinue'
} }
Invoke-Command @CmdSplat | Out-Null Invoke-Command @cmdSplat | Out-Null
} }
<# <#
Here we've invoked jobs across many servers Here we've invoked jobs across many servers.
We can now Receive-Job and see if they're all running We can now Receive-Job and see if they're all running.
Now scale this up 100x as many servers :) Now scale this up 100x as many servers :)
#> #>
``` ```