// this will send either Ctrl-C or Ctrl-Break to runner.listener // Ctrl-C will be used for OnStop() // Ctrl-Break will be used for OnShutdown() private void SendCtrlSignalToRunnerListener(uint signal) { try { if (RunnerListener != null && !RunnerListener.HasExited) { // Try to let the runner process know that we are stopping //Attach service process to console of Runner.Listener process. This is needed, //because windows service doesn't use its own console. if (AttachConsole((uint)RunnerListener.Id)) { //Prevent main service process from stopping because of Ctrl + C event with SetConsoleCtrlHandler SetConsoleCtrlHandler(null, true); try { //Generate console event for current console with GenerateConsoleCtrlEvent (processGroupId should be zero) GenerateConsoleCtrlEvent(signal, 0); //Wait for the process to finish (give it up to 30 seconds) RunnerListener.WaitForExit(30000); } finally { //Disconnect from console and restore Ctrl+C handling by main process FreeConsole(); SetConsoleCtrlHandler(null, false); } } // if runner is still running, kill it if (!RunnerListener.HasExited) { RunnerListener.Kill(); } } } catch (Exception exception) { // InvalidOperationException is thrown when there is no process associated to the process object. // There is no process to kill, Log the exception and shutdown the service. // If we don't handle this here, the service get into a state where it can neither be stoped nor restarted (Error 1061) WriteException(exception); } }