Send ctrl-C to a Windows shell

I found a solution, but I’m not marking it as an answer just yet as I’d still like to hear from an engineer.

Starting with this post, I came up with the following code based on declares:

  #if TargetWindows then
    declare function AttachConsole lib kWindowsLib (dbProcessId As UInt32) As Boolean
    declare function GenerateConsoleCtrlEvent lib kWindowsLib (dwCtrlEvent as Int32, dwProcessGroupId As UInt32) As Boolean
    
    if AttachConsole( PID.Val ) then
      call SetConsoleCtrlHandler( nil, true )
      call GenerateConsoleCtrlEvent( 0, 0 )
      DoWindowsTeardown = true
    end if
    
  #else
    static ctrlC as string = ChrB( 3 ).DefineEncoding( nil )
    ServerShell.Write ctrlC
  #endif

When the shell is being torn down, it executes this:

#if TargetWindows then
  if DoWindowsTeardown then
    declare function FreeConsole lib kWindowsLib () As Boolean
    
    call SetConsoleCtrlHandler( nil, false )
    call FreeConsole()
    
    DoWindowsTeardown = false
  end if
#endif

The SetConsoleCtrlHandler is defined as an external method like this:

Private Function SetConsoleCtrlHandler(handler As Ptr, add As Boolean) as Boolean

And kWindowsLib = "kernel32.dll"

Finally, PID.Val is the actual PID of my running process, not the one reported by Shell.PID. Fortunately, redis-server reports that back to me when it starts.

I have no idea if I’m doing the right thing but it certainly works the way I want it. My server is signaled to stop just as if I had pressed ctrl-C in the Terminal and cleans itself up.