# encoding: ascii
# api: powershell
# title: DEMO: Trap Ctrl+C
# description: This is a demo of one way you could implement handling Ctrl+C (CancelKeyPressed) without using PSEvent or PInvoke …
# version: 0.1
# type: function
# author: Joel Bennett
# license: CC0
# function: Trap-CtrlC
# x-poshcode-id: 542
# x-archived: 2017-03-10T06:14:41
# x-published: 2009-08-20T16:04:00
#
#
function Trap-CtrlC {
   ## Stops Ctrl+C from exiting this function
   [console]::TreatControlCAsInput = $true
   ## And you have to check every keystroke to see if it's a Ctrl+C
   ## As far as I can tell, for CtrlC the VirtualKeyCode will be 67 and 
   ## The ControlKeyState will include either "LeftCtrlPressed" or "RightCtrlPressed" 
   ## Either of which will -match "CtrlPressed"
   ## But the simplest thing to do is just compare Character = [char]3
   if ($Host.UI.RawUI.KeyAvailable -and (3 -eq [int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,NoEcho").Character))
   {
      throw (new-object ExecutionEngineException "Ctrl+C Pressed")
   }
}

function Test-CtrlCIntercept {
   Trap-CtrlC  # Call Trap-CtrlC right away to turn on TreatControlCAsInput 
   ## Do your work ...
   while($true) { 
      $i = ($i+1)%16
      Trap-CtrlC ## Constantly check ...
      write-host (Get-Date) -fore ([ConsoleColor]$i) -NoNewline
      foreach($sleep in 1..4) {
         Trap-CtrlC ## Constantly check ...
         sleep -milli 500; ## Do a few things ...
         Write-Host "." -fore ([ConsoleColor]$i) -NoNewline
      }
      Write-Host
   }
   
   trap [ExecutionEngineException] { 
      Write-Host "Exiting now, don't try to stop me...." -Background DarkRed
      continue # Be careful to do the right thing here (or just don't do anything)
   }
}



## Another way to do the same thing without an external function ....
## Don't use this way unless your loop is really tight ...
## If you use this and hit CTRL+C right after a timestamp is printed, 
## you'll notice the 2 second delay (compared with above)
function Test-CtrlCIntercept { 
   ## Stops Ctrl+C from exiting this function
   [console]::TreatControlCAsInput = $true
   ## Do your work here ...
   while($true) { 
      $i = ($i+1)%16
      write-host (Get-Date) -fore ([ConsoleColor]$i)
      sleep 2; 
      ## You have to be constantly checking for KeyAvailable
      ## And you have to check every keystroke to see if it's a Ctrl+C
      ## As far as I can tell, for CtrlC the VirtualKeyCode will be 67 and 
      ## The ControlKeyState will include either "LeftCtrlPressed" or "RightCtrlPressed" 
      ## Either of which will -match "CtrlPressed"
      ## But the simplest thing to do is just compare Character = [char]3
      if ($Host.UI.RawUI.KeyAvailable -and (3 -eq [int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,NoEcho").Character))
      {
         Write-Host "Exiting now, don't try to stop me...." -Background DarkRed
         break;
      }
   }
}
