PoshCode Logo PowerShell Code Repository

Start-Demo 3.3.3 by Joel Bennett 8 years ago (modification of post by Joel Bennett view diff)
View followups from Wojciech Sciesin | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/705"></script>download | new post

This is an overhaul of Jeffrey Snover’s original Start-Demo script … I’ve switched it to use ReadKey, which saves you some typing and makes the whole thing seem more natural when you’re demoing, (at least to me). I’ve also added a bunch of command-line options and a couple of features in the process (see the Revision History in the script).

  1. ## Start-Demo.ps1
  2. ##################################################################################################
  3. ## This is an overhaul of Jeffrey Snover's original Start-Demo script by Joel "Jaykul" Bennett
  4. ##
  5. ## I've switched it to using ReadKey instead of ReadLine (you don't have to hit Enter each time)
  6. ## As a result, I've changed the names and keys for a lot of the operations, so that they make
  7. ## sense with only a single letter to tell them apart (sorry if you had them memorized).
  8. ##
  9. ## I've also been adding features as I come across needs for them, and you'll contribute your
  10. ## improvements back to the PowerShell Script repository as well.
  11. ##################################################################################################
  12. ## Revision History (version 3.3)
  13. ## 3.3.3 Fixed:    Script no longer says "unrecognized key" when you hit shift or ctrl, etc.
  14. ##       Fixed:    Blank lines in script were showing as errors (now printed like comments)
  15. ## 3.3.2 Fixed:    Changed the "x" to match the "a" in the help text
  16. ## 3.3.1 Fixed:    Added a missing bracket in the script
  17. ## 3.3 - Added:    Added a "Clear Screen" option
  18. ##     - Added:    Added a "Rewind" function (which I'm not using much)
  19. ## 3.2 - Fixed:    Put back the trap { continue; }
  20. ## 3.1 - Fixed:    No Output when invoking Get-Member (and other cmdlets like it???)
  21. ## 3.0 - Fixed:    Commands which set a variable, like: $files = ls
  22. ##     - Fixed:    Default action doesn't continue
  23. ##     - Changed:  Use ReadKey instead of ReadLine
  24. ##     - Changed:  Modified the option prompts (sorry if you had them memorized)
  25. ##     - Changed:  Various time and duration strings have better formatting
  26. ##     - Enhance:  Colors are settable: prompt, command, comment
  27. ##     - Added:    NoPauseAfterExecute switch removes the extra pause
  28. ##                 If you set this, the next command will be displayed immediately
  29. ##     - Added:    Auto Execute mode (FullAuto switch) runs the rest of the script
  30. ##                 at an automatic speed set by the AutoSpeed parameter (or manually)
  31. ##     - Added:    Automatically append an empty line to the end of the demo script
  32. ##                 so you have a chance to "go back" after the last line of you demo
  33. ##################################################################################################
  34. ##
  35. param(
  36.   $file=".\demo.txt",
  37.   [int]$command=0,
  38.   [System.ConsoleColor]$promptColor="Yellow",
  39.   [System.ConsoleColor]$commandColor="White",
  40.   [System.ConsoleColor]$commentColor="Green",
  41.   [switch]$FullAuto,
  42.   [int]$AutoSpeed = 3,
  43.   [switch]$NoPauseAfterExecute
  44. )
  45.  
  46. $RawUI = $Host.UI.RawUI
  47. $hostWidth = $RawUI.BufferSize.Width
  48.  
  49. # A function for reading in a character
  50. function Read-Char() {
  51.   $_OldColor = $RawUI.ForeGroundColor
  52.   $RawUI.ForeGroundColor = "Red"
  53.   $inChar=$RawUI.ReadKey("IncludeKeyUp")
  54.   # loop until they press a character, so Shift or Ctrl, etc don't terminate us
  55.   while($inChar.Character -eq 0){
  56.     $inChar=$RawUI.ReadKey("IncludeKeyUp")
  57.   }
  58.   $RawUI.ForeGroundColor = $_OldColor
  59.   return $inChar.Character
  60. }
  61.  
  62. function Rewind($lines, $index, $steps = 1) {
  63.    $started = $index;
  64.    $index -= $steps;
  65.    while(($index -ge 0) -and ($lines[$index].Trim(" `t").StartsWith("#"))){
  66.       $index--
  67.    }
  68.    if( $index -lt 0 ) { $index = $started }
  69.    return $index
  70. }
  71.  
  72. $file = Resolve-Path $file
  73. while(-not(Test-Path $file)) {
  74.   $file = Read-Host "Please enter the path of your demo script (Crtl+C to cancel)"
  75.   $file = Resolve-Path $file
  76. }
  77.  
  78. Clear-Host
  79.  
  80. $_lines = Get-Content $file
  81. # Append an extra (do nothing) line on the end so we can still go back after the last line.
  82. $_lines += "Write-Host 'The End'"
  83. $_starttime = [DateTime]::now
  84. $FullAuto = $false
  85.  
  86. Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth)
  87. Write-Host -nonew -back black -fore $promptColor @"
  88. <Demo Started :: $(split-path $file -leaf)>$(' ' * ($hostWidth -(18 + $(split-path $file -leaf).Length)))
  89. "@
  90. Write-Host -nonew -back black -fore $promptColor "Press"
  91. Write-Host -nonew -back black -fore Red " ? "
  92. Write-Host -nonew -back black -fore $promptColor "for help.$(' ' * ($hostWidth -17))"
  93. Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth)
  94.  
  95. # We use a FOR and an INDEX ($_i) instead of a FOREACH because
  96. # it is possible to start at a different location and/or jump
  97. # around in the order.
  98. for ($_i = $Command; $_i -lt $_lines.count; $_i++)
  99. {  
  100.         # Put the current command in the Window Title along with the demo duration
  101.         $Dur = [DateTime]::Now - $_StartTime
  102.    $RawUI.WindowTitle = "$(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s   {3}" -f
  103.                         $dur.Hours, $dur.Minutes, $dur.Seconds, $($_Lines[$_i])
  104.  
  105.         # Echo out the commmand to the console with a prompt as though it were real
  106.         Write-Host -nonew -fore $promptColor "[$_i]$([char]0x2265) "
  107.         if ($_lines[$_i].Trim(" ").StartsWith("#") -or $_lines[$_i].Trim(" ").Length -le 0) {
  108.                 Write-Host -fore $commentColor "$($_Lines[$_i])  "
  109.                 continue
  110.         } else {
  111.                 Write-Host -nonew -fore $commandColor "$($_Lines[$_i])  "
  112.         }
  113.  
  114.         if( $FullAuto ) { Start-Sleep $autoSpeed; $ch = [char]13 } else { $ch = Read-Char }
  115.         switch($ch)
  116.         {
  117.                 "?" {
  118.                         Write-Host -Fore $promptColor @"
  119.  
  120. Running demo: $file
  121. (n) Next       (p) Previous
  122. (q) Quit       (s) Suspend
  123. (t) Timecheck  (v) View $(split-path $file -leaf)
  124. (g) Go to line by number
  125. (f) Find lines by string
  126. (a) Auto Execute mode
  127. (c) Clear Screen
  128. "@
  129.                         $_i-- # back a line, we're gonna step forward when we loop
  130.                 }
  131.                 "n" { # Next (do nothing)
  132.                         Write-Host -Fore $promptColor "<Skipping Line>"
  133.                 }
  134.                 "p" { # Previous
  135.                         Write-Host -Fore $promptColor "<Back one Line>"
  136.                         while ($_lines[--$_i].Trim(" ").StartsWith("#")){}
  137.                         $_i-- # back a line, we're gonna step forward when we loop
  138.                 }
  139.                 "a" { # EXECUTE (Go Faster)
  140.                         $AutoSpeed = [int](Read-Host "Pause (seconds)")
  141.                         $FullAuto = $true;
  142.                         Write-Host -Fore $promptColor "<eXecute Remaining Lines>"
  143.                         $_i-- # Repeat this line, and then just blow through the rest
  144.                 }
  145.                 "q" { # Quit
  146.                         Write-Host -Fore $promptColor "<Quiting demo>"
  147.                         $_i = $_lines.count;
  148.                         break;
  149.                 }
  150.                 "v" { # View Source
  151.                         $lines[0..($_i-1)] | Write-Host -Fore Yellow
  152.                         $lines[$_i]        | Write-Host -Fore Green
  153.                         $lines[($_i+1)..$lines.Count] | Write-Host -Fore Yellow
  154.                         $_i-- # back a line, we're gonna step forward when we loop
  155.                 }
  156.                 "t" { # Time Check
  157.                          $dur = [DateTime]::Now - $_StartTime
  158.        Write-Host -Fore $promptColor $(
  159.           "{3} -- $(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s" -f
  160.           $dur.Hours, $dur.Minutes, $dur.Seconds, ([DateTime]::Now.ToShortTimeString()))
  161.                          $_i-- # back a line, we're gonna step forward when we loop
  162.                 }
  163.                 "s" { # Suspend (Enter Nested Prompt)
  164.                         Write-Host -Fore $promptColor "<Suspending demo - type 'Exit' to resume>"
  165.                         $Host.EnterNestedPrompt()
  166.                         $_i-- # back a line, we're gonna step forward when we loop
  167.                 }
  168.                 "g" { # GoTo Line Number
  169.                         $i = [int](Read-Host "line number")
  170.                         if($i -le $_lines.Count) {
  171.                                 if($i -gt 0) {
  172.                # extra line back because we're gonna step forward when we loop
  173.                $_i = Rewind $_lines $_i (($_i-$i)+1)
  174.                                 } else {
  175.                                         $_i = -1 # Start negative, because we step forward when we loop
  176.                                 }
  177.                         }
  178.                 }
  179.                 "f" { # Find by pattern
  180.                         $match = $_lines | Select-String (Read-Host "search string")
  181.                         if($match -eq $null) {
  182.                                 Write-Host -Fore Red "Can't find a matching line"
  183.                         } else {
  184.                                 $match | % { Write-Host -Fore $promptColor $("[{0,2}] {1}" -f ($_.LineNumber - 1), $_.Line) }
  185.                                 if($match.Count -lt 1) {
  186.                                         $_i = $match.lineNumber - 2  # back a line, we're gonna step forward when we loop
  187.                                 } else {              
  188.                                         $_i-- # back a line, we're gonna step forward when we loop
  189.                                 }
  190.                         }
  191.                 }
  192.       "c" {
  193.          Clear-Host
  194.          $_i-- # back a line, we're gonna step forward when we loop
  195.       }
  196.                 "$([char]13)" { # on enter
  197.                         Write-Host
  198.                         trap [System.Exception] {Write-Error $_; continue;}
  199.                         Invoke-Expression ($_lines[$_i]) | out-default
  200.                         if(-not $NoPauseAfterExecute -and -not $FullAuto) {
  201.                                 $null = $RawUI.ReadKey("NoEcho,IncludeKeyUp")  # Pause after output for no apparent reason... ;)
  202.                         }
  203.                 }
  204.                 default
  205.                 {
  206.                         Write-Host -Fore Green "`nKey not recognized.  Press ? for help, or ENTER to execute the command."
  207.                         $_i-- # back a line, we're gonna step forward when we loop
  208.                 }
  209.         }
  210. }
  211. $dur = [DateTime]::Now - $_StartTime
  212. Write-Host -Fore $promptColor $(
  213.    "<Demo Complete -- $(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s>" -f
  214.    $dur.Hours, $dur.Minutes, $dur.Seconds, [DateTime]::Now.ToLongTimeString())
  215. Write-Host -Fore $promptColor $([DateTime]::now)
  216. Write-Host
  217. # SIG # Begin signature block
  218. # MIIIPgYJKoZIhvcNAQcCoIIILzCCCCsCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  219. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  220. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUhnYBsMQ+7cZlmxCQp6UPJj6A
  221. # u0GgggVbMIIFVzCCBD+gAwIBAgIRAO2rPg5HUjL4ofGGpnMP2jwwDQYJKoZIhvcN
  222. # AQEFBQAwgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2Fs
  223. # dCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8G
  224. # A1UECxMYaHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNF
  225. # UkZpcnN0LU9iamVjdDAeFw0wODEwMDYwMDAwMDBaFw0wOTEwMDYyMzU5NTlaMIHE
  226. # MQswCQYDVQQGEwJVUzEOMAwGA1UEEQwFMTQ2MjMxETAPBgNVBAgMCE5ldyBZb3Jr
  227. # MRIwEAYDVQQHDAlSb2NoZXN0ZXIxFDASBgNVBAkMC01TIDA4MDEtMTdBMRowGAYD
  228. # VQQJDBExMzUwIEplZmZlcnNvbiBSZDEaMBgGA1UECgwRWGVyb3ggQ29ycG9yYXRp
  229. # b24xFDASBgNVBAsMC1NFRURVIFRvb2xzMRowGAYDVQQDDBFYZXJveCBDb3Jwb3Jh
  230. # dGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK50RXT2KUvECfWZ
  231. # weqeXzTCykPPRh9nC3Hzur/mmvkQHA8iinnSKX4j19C1/MV0rAEeCU1bF7Sgxvov
  232. # ORreM1Ye/wEqJLAUP/IGZI/qsmmwasGFGbnuevpA3WieNCr5cFGl8Y5Mx6ejaDFi
  233. # O0GT9EM6gOGZaEEMRbHZc4qXT7CrWScs4Yur5bBZsowaMk5JkvZgihhnN93QolEW
  234. # ObmtQZlbBDqLuoL9fUnIexlqqIrC/4h0K8VM26HvqhgGlQF2wf4t9xCHFJiX2F7D
  235. # B10lef5aXzyPVrvxxrRWyBtCQuL7xdXneRanJaYG3B3kclc+4/6dq9a+s/huXjmE
  236. # omumgGcCAwEAAaOCAW8wggFrMB8GA1UdIwQYMBaAFNrtZHQUnBQ8q92Zqb1bKE2L
  237. # PMnYMB0GA1UdDgQWBBT5ITlG5CdiD+nI0uTqnXNGnd44QjAOBgNVHQ8BAf8EBAMC
  238. # B4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglghkgBhvhC
  239. # AQEEBAMCBBAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwIwKzApBggrBgEFBQcC
  240. # ARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwQgYDVR0fBDswOTA3oDWg
  241. # M4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0
  242. # LmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNv
  243. # bW9kb2NhLmNvbTAhBgNVHREEGjAYgRZKb2VsLkJlbm5ldHRAWGVyb3guY29tMA0G
  244. # CSqGSIb3DQEBBQUAA4IBAQAZxnV+BbJBohpy+wKs6U8hRiPUhDYaijzTyrZontf5
  245. # PEyBbhAkJFIWauIaq9eSQEJeErXO/zuO6+wY/azBzOTleMM9qdGWHFtfAw5WiIuC
  246. # 90TzDBSuP7LImZV5Pb6nxRbesDF2U7EM5sBzYSWAMfpBmYRz97EHPW5QNzpBLFJn
  247. # Dhb/M27rDYh7FVjy1+C5E3glIa0A0q+lcxEtFuUij4JId+oMcfpSgYJZvR1Kvkjd
  248. # GDAtWCzvALaNFd65kChbrOqcClOCacQRnP9N4DJl/RVNKZtcUcVAyTpvOlJBA5vG
  249. # OVcsJT4TnSMjPX6d5pXMwcE1oWCUWvK99W+N81DvBBuZMYICTTCCAkkCAQEwgasw
  250. # gZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
  251. # IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
  252. # aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0
  253. # LU9iamVjdAIRAO2rPg5HUjL4ofGGpnMP2jwwCQYFKw4DAhoFAKB4MBgGCisGAQQB
  254. # gjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK
  255. # KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFNEM/yDz
  256. # vLFTxZZERqngy81y1rFyMA0GCSqGSIb3DQEBAQUABIIBAIi+6WT4dPUfVZyJ1Efd
  257. # DzTqYmH2wmcGg8KncjeA2vi+F3+9EPDIMRUSNxDO+l/iAel4uiNE3CNlZDiCfi4v
  258. # W+nc1TTpen1q33ITFLgFaUvMztgJ1D02NsEIAsGX0Qu9FHYXXGkdx6HiTyy5lfl2
  259. # sLvmQiINVfHJnn28YhSqpEByebojR6177/VhDqk7h9vvhMhuBP+XWlzO+nwaZ84T
  260. # BcS8Qb/JkKxkhKYhbsfViQX0Rq4/5MjhjR7ctEJvCfkb0dkY97sHddg4kWGy5amI
  261. # ydV6EoqjHHUJatdgmCc38KIQVdXvaZyC5rTRg/uEJias4BQq3HLdUQDJ+u5l0EeY
  262. # MbI=
  263. # SIG # End signature block

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me