Orlando2017PowerShellUnplugged.ps1
<#PSScriptInfo .VERSION 1.0 .GUID f81b0e01-207e-4364-84a9-67d59d900edc .AUTHOR Jeffrey Snover .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION This is the demo file that I used for my PowerShell Unplugged demos at IT Transformation in Florida 2017 #> function functionDemo { <# Discuss Scoping/Dynamic scoping (set a breakpoint and use VSCode to illustrate) Change $color to $otherColor to illustrate Dynamic scoping Explore VSCode Debugging: Breakpoints, Call Stack, Watch Advanced Breakpoints: hitcount, -Action Variable Watchpoints: Set-PSBreakpoint -Variable color -mode read -action {} #> $whackyColor = "red"; function Hello ($name = "???", $color = "red") { $whackyColor = "blue"; $s = "Hello " $s += $name write-output "************************" write-host -ForegroundColor $Color $s return $s } $whackyColor = "red" $whackyColor = "black" $OtherColor = "green" Hello World Hello Florida Yellow Hello Jeffrey Green return } function Class1Demo { <# Classes provide a stronger contract. - show errors with: No return, misspelled names - Change $color to $otherColor to illustrate Dynamic scoping doesn't work in classes - Write-Output is ignored New Constructor #> class Friendly { [string] Hello($name) { $color = "red" $s = "Hello " $s += $name write-output "************************" write-host -ForegroundColor $color $s if ($color -eq "red") { return $s } else { return "test" } } } $OtherColor = "green" $f = [Friendly]::new() $f.Hello("world") $f.Hello("Jeffrey") return } function ClassMethodOverloadDemo { <# methods don't have default values so you have to have multiple signatures #> class Friendly2 { [String] Hello($name, $color) { $s = "Hello " $s += $name write-output "************************" write-host -ForegroundColor $color $s return $s } [String] Hello($name) { return $this.Hello($name, "red") } [String] Hello() { return $this.Hello("Jeffrey") } } $OtherColor = "green" $f = [Friendly2]::new() $f.Hello("World", "green") $f.Hello("Florida") $f.Hello() return } function ClassSubclassDemo { <# classes give more structure. Base class allows you to define contracts for other people Those contracts strike a balance between control & expression MountainBike Constructors $b = [MountainBike]::new($(read-host -prompt color)) enum BikeColor {red; green;blue; purple;} [int]GetMaxSpeed() {return 0} [int]GetMaxSpeed() { $x = switch ($this.color) { "red" {20} "blue" {30} "green" {40} } return $x } #> class Bike { [Int]$Cost; [String]$Color; [int]GetMaxSpeed() {return 0} } class RoadBike : Bike { RoadBike() { $this.Color = "Red" $this.Cost = "500" } [int]GetMaxSpeed() {return 10} } class MountainBike : Bike { MountainBike($color, $cost) { $this.Color = $color $this.Cost = $cost } MountainBike($color) { $this.Color = $color $this.Cost = switch ($color) { "red" {1000} "blue" {1100} "green" {1500} } } } function foo ([Bike]$bike) { "The bike is {0} and costs {1}" -f $b.color, $b.cost} $b = [RoadBike]::new() foo -bike $b $b = [MountainBike]::new("blue") foo -bike $b return } function RemotingV6Demo { <# #> $script = { class Bike2 { [Int]$Cost; [String]$Color; [int]GetMaxSpeed() {return 0} } class RoadBike2 : Bike2 { RoadBike2() { $this.Color = "Red" $this.Cost = "500" } [int]GetMaxSpeed() {return 10} } class MountainBike2 : Bike2 { MountainBike2($color, $cost) { $this.Color = $color $this.Cost = $cost } MountainBike2($color) { $this.Color = $color $this.Cost = switch ($color) { "red" {1000} "blue" {1100} "green" {1500} } } } function foo ([Bike2]$bike) { "{2}: The bike is {0} and costs {1}" -f $b.color, $b.cost, (hostname)} $b = [RoadBike2]::new() foo -bike $b $b = [MountainBike2]::new("blue") foo -bike $b } $s = nsn -cn localhost invoke-command $s -ScriptBlock $script remove-pssession $s return } function ETSDemo1 { $g = get-process *ss # Objects $g |get-member $g |get-member e* } function DemoETSEvents { calc Start-Sleep -Seconds 1 $p = gps calc* Register-ObjectEvent -InputObject $p -EventName Exited -Action { write-host -ForegroundColor red "Calc exited"} } function DemoETSExtendProperties { $g = get-process *ss $g | get-member -MemberType PropertySet $g | select PSResources $g | sort PSResources $G1 = $G[0] $G1.PSTYPENAMES $G1.PSOBJECT $G1.PSSTANDARDMEMBERS $G1.PSSTANDARDMEMBERS.DefaultDisplayPropertySet # I forgot how to add one so: gps |gm -MemberType PropertySet get-command -ParameterName membertype add-member -TypeName System.Diagnostics.Process -MemberType PropertySet -Name Test -Value name, id, company, description add-type -TypeDefinition System.Diagnostics.Process - } $global:GlobalScope = "Global Scope" $ScriptScope = "In Script Scope" cls functionDemo #Class1Demo #classMethodOverloadDemo #ClassSubclassDemo #RemotingV6Demo #ETSDemo1 #DemoETSEvents #DemoETSExtendProperties #DemoXML |