I have a simple library that overrides a console's shutdown events to complete various tasks before closing itself. This works whenever a user or external program closes the console (ctrl+C, close window, etc), however, when the console app uses Environment.Exit() it closes without being recognised as one of the shutdown events.
Here is the code for the shutdown handler:
namespace ShutdownLibrary
{
public class ConsoleHandler
{
public bool ExitSystem = false; // Optional assistance for implementation.
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
private EventHandler _handler;
/// <summary>
/// Windows events to listen for.
/// </summary>
public enum CtrlType
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6,
}
private bool Handler(CtrlType sig)
{
//Old .NET threading
var result = Task.Factory.StartNew<bool>(ShutdownTasks);
result.Wait();
return result.Result;
}
/// <summary>
/// Starts an EventHandler for console windows & calls overridable ShutdownTasks() when console is closed by any means.
/// </summary>
public void StartShutdownEventHandler()
{
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
}
/// <summary>
/// Overridable method for tasks to action before the program is disposed.
/// </summary>
/// <returns>True when complete. False when not implemented.</returns>
public virtual bool ShutdownTasks()
{
ExitSystem = false;
return false;
}
}
}
The app itself consumes the shutdown handler (ConsoleHandler) like this:
class ManagementServer : ServerManager
{
internal class ShutdownManager : ConsoleHandler
{
public override bool ShutdownTasks()
{
base.ShutdownTasks();
for (var i = 5; i >= 0; i--)
{
Thread.Sleep(1000);
Log.WriteToLog(string.Format("Management Server Shutting down in {0}", i));
}
Console.WriteLine("Good bye!");
return true;
}
}
//Override from ServerManager
public override void ShutDownManagementServer()
{
base.ShutDownManagementServer();
Environment.Exit(0);
}
static void Main(string[] args)
{
var sm = new ShutdownManager();
sm.StartShutdownEventHandler();
var manager = new ManagementServer();
manager.StartServer();
}
}
I think the CtrlType enum in the ConsoleHandler class is the main culprit, but I can't seem to figure out what values are missing.
Any ideas?