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
35 / 5 # => 7.0
# Powershell uses banker's rounding
# 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
# Powershell uses banker's rounding,
# 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.
[int]5 / [int]3 # => 1.66666666666667
[int]-5 / [int]3 # => -1.66666666666667
5.0 / 3.0 # => 1.66666666666667
@ -55,10 +56,10 @@ Powershell as a Language:
# Modulo operation
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
# Enforce order of operations with parentheses
# Enforce order of operations with parentheses.
1 + 3 * 2 # => 7
(1 + 3) * 2 # => 8
@ -75,20 +76,20 @@ $False # => False
$True -and $False # => False
$False -or $True # => True
# True and False are actually 1 and 0 but only support limited arithmetic
# However, casting the bool to int resolves this
# True and False are actually 1 and 0 but only support limited arithmetic.
# However, casting the bool to int resolves this.
$True + $True # => 2
$True * 8 # => '[System.Boolean] * [System.Int32]' is undefined
[int]$True * 8 # => 8
$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
1 -eq $True # => True
2 -eq $True # => False
-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
# Don't mix up with bool(ints) and bitwise -band/-bor
[bool](0) # => False
@ -115,10 +116,10 @@ $False - 5 # => -5
1 -lt 2 -and 2 -lt 3 # => True
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.
# 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
$a = (1,2,3,4)
$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
("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"
$age = 22
"He said his name is $name." # => "He said his name is Steve"
"{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."
"He said his name is $name."
# => "He said his name is Steve"
"{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
# 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.
# All other values are True
function test ($value) {
function Test-Value ($value) {
if ($value) {
Write-Output 'True'
}
@ -175,12 +179,13 @@ function test ($value) {
}
}
test ($null) # => False
test (0) # => False
test ("") # => False
test [] # => True *[] calls .NET classes; creates '[]' string when passed to func
test ({}) # => True
test @() # => False
Test-Value ($null) # => False
Test-Value (0) # => False
Test-Value ("") # => False
Test-Value [] # => True
# *[] calls .NET class; creates '[]' string when passed to function
Test-Value ({}) # => True
Test-Value @() # => False
####################################################
@ -205,9 +210,9 @@ $someVariable # => 5
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"
# 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."
# To have a more workable array, you'll want the .NET [ArrayList] class
# 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
[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)
$array.add(1) > $null # $array is now [1]
$array.add(2) > $null # $array is now [1, 2]
$array.add(4) > $null # $array is now [1, 2, 4]
$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
# 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(2) > $null # $array is now [1, 2]
$array.Add(4) > $null # $array is now [1, 2, 4]
$array.Add(3) > $null # $array is now [1, 2, 4, 3]
# 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]
# Let's put it back
$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"
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
# 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.Item(0) # => 1
$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 + (4, 5, 6) # => Exception
$tuple[0..2] # => $null
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 = @{}
# Here is a prefilled dictionary
$filledHash = @{"one"= 1
@ -294,10 +299,10 @@ $filledHash["one"] # => 1
# Get all keys as an iterable with ".Keys".
# 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".
$filledHash.values # => [1, 2, 3]
$filledHash.Values # => [1, 2, 3]
# Check for existence of keys or values in a hash with "-in"
"one" -in $filledHash.Keys # => True
@ -309,7 +314,7 @@ $filledHash["four"] # $null
# Adding to a dictionary
$filledHash.Add("five",5) # $filledHash["five"] is set to 5
$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
$filledHash.Remove("one") # Removes the key "one" from filled dict
@ -428,8 +433,8 @@ Add-Numbers 1 2 # => 3
# Calling functions with parameters
function Add-ParamNumbers {
param( [int]$FirstNumber, [int]$SecondNumber )
$FirstNumber + $SecondNumber
param( [int]$firstNumber, [int]$secondNumber )
$firstNumber + $secondNumber
}
Add-ParamNumbers -FirstNumber 1 -SecondNumber 2 # => 3
@ -457,9 +462,9 @@ function New-Website() {
[ValidateSet(3000,5000,8000)]
[int]$port = 3000
)
BEGIN { Write-Verbose 'Creating new website(s)' }
BEGIN { Write-Output 'Creating new website(s)' }
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
####################################################
# Inheritance allows new child classes to be defined that inherit methods and
# variables from their parent class.
# Inheritance allows new child classes to be defined that inherit
# methods and variables from their parent class.
class Guitar : Instrument
{
@ -551,67 +556,68 @@ True False Guitar Instrument
## 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
# It works much like a GROUP BY in SQL would
# Group-Object is a handy cmdlet that does incredible things.
# It works much like a GROUP BY in SQL.
<#
The following will get all the running processes
Group them by Name
And tell us how many instances of each process we have running
Tip: Chrome and svcHost are usually big numbers in this regard
The following will get all the running processes,
group them by Name,
and tell us how many instances of each process we have running.
Tip: Chrome and svcHost are usually big numbers in this regard.
#>
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 | Where-Object { $PSITEM -gt 5 } | ConvertTo-Json
# A noteable pitfall of the pipeline is it's performance when
# compared with other options
# Additionally, raw bytes are not passed through the pipeline
# so passing an image causes some issues
# See more on that in the link at the bottom
# A notable pitfall of the pipeline is it's performance when
# compared with other options.
# Additionally, raw bytes are not passed through the pipeline,
# so passing an image causes some issues.
# See more on that in the link at the bottom.
<#
Asynchronous functions exist in the form of jobs
Typically a procedural language
Powershell can operate many non-blocking functions when invoked as Jobs
Asynchronous functions exist in the form of jobs.
Typically a procedural language,
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
# 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}
Start-Job -ScriptBlock $scriptBlock
# This will start a background job that runs the command
# You can then obtain the status of jobs and their returned results
# This will start a background job that runs the command.
# You can then obtain the status of jobs and their returned results.
$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
$pi=[math]::pi
$r2=[math]::pow( $r, 2 )
$Area = $pi*$r2
$Area
$area = $pi*$r2
$area
# To see all possibilities, check the members
# To see all possibilities, check the members.
[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
and reverse anything in an array within the given range
based on an arbitrary array without mutating the original array
Let's see one way to do that and introduce another data structure
based on an arbitrary array without mutating the original array.
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) {
[System.Collections.ArrayList]$firstSectionArray = @()
@ -628,16 +634,16 @@ function Format-Range ($start, $end) {
$secondSectionArray.Add($targetArray[$index]) > $null
}
}
$returnArray = $firstSectionArray + $stack.ToArray() + $secondSectionArray
Write-Output $returnArray
$finalArray = $firstSectionArray + $stack.ToArray() + $secondSectionArray
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
# It's also kind of lengthy
# Let's see how we can do this without allocating a new array
# This is slightly faster as well
# The previous method works, but uses extra memory by allocating new arrays.
# It's also kind of lengthy.
# Let's see how we can do this without allocating a new array.
# This is slightly faster as well.
function Format-Range ($start, $end) {
while ($start -lt $end)
@ -651,7 +657,7 @@ function Format-Range ($start, $end) {
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:
@ -688,22 +694,26 @@ $PSVersionTable
```
```Powershell
# Calling external commands, executables, and functions with the call operator.
# Executables with arguments passed create issues
# Calling external commands, executables,
# and functions with the call operator.
# Exe paths with arguments passed or containing spaces can create issues.
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.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again
# The term 'C:\Program' is not recognized as a name of a cmdlet,
# 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 # 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 # success
# Alternatively, you can use dot-sourcing here
."C:\Program Files\dotnet\dotnet.exe" --help # success
# the call operator (&) is similar to Invoke-Expression, but IEX runs in current scope.
# Standard usage of '&' would be to invoke a scriptblock inside of your script.
# the call operator (&) is similar to Invoke-Expression,
# but IEX runs in current scope.
# One usage of '&' would be to invoke a scriptblock inside of your script.
# Notice the variables are scoped
$i = 2
$scriptblock = { $i=5; Write-Output $i }
@ -714,17 +724,17 @@ invoke-expression ' $i=5; Write-Output $i ' # => 5
$i # => 5
# 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=2};$x # => 1
.{$x=2};$x # => 2
# Remoting into computers is easy
# Remoting into computers is easy.
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
<#
@ -736,10 +746,10 @@ Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
RemoteComputer\PS> Exit-PSSession
<#
Powershell is an incredible tool for Windows management and Automation
Let's take the following scenario
You have 10 servers
You need to check whether a service is running on all of them
Powershell is an incredible tool for Windows management and Automation.
Let's take the following scenario:
You have 10 servers.
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?
Check out the following
#>
@ -757,24 +767,24 @@ $serverList = @(
'server10'
)
[scriptblock]$Script = {
[scriptblock]$script = {
Get-Service -DisplayName 'Task Scheduler'
}
foreach ($server in $serverList) {
$CmdSplat = @{
ComputerName = $Server
$cmdSplat = @{
ComputerName = $server
JobName = 'checkService'
ScriptBlock = $Script
ScriptBlock = $script
AsJob = $true
ErrorAction = 'SilentlyContinue'
}
Invoke-Command @CmdSplat | Out-Null
Invoke-Command @cmdSplat | Out-Null
}
<#
Here we've invoked jobs across many servers
We can now Receive-Job and see if they're all running
Here we've invoked jobs across many servers.
We can now Receive-Job and see if they're all running.
Now scale this up 100x as many servers :)
#>
```