using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; namespace MinecraftClient.WinAPI { /// /// Perform clean up before quitting application /// /// /// Only ctrl+c/ctrl+break will be captured when running on mono /// public static class ExitCleanUp { /// /// Store codes to run before quitting /// private static readonly List actions = new(); static ExitCleanUp() { try { // Capture all close event _handler += CleanUp; // Use delegate directly cause program to crash SetConsoleCtrlHandler(_handler, true); } catch (DllNotFoundException) { // Probably on mono, fallback to ctrl+c only static void value(object sender, ConsoleCancelEventArgs e) { RunCleanUp(); } Console.CancelKeyPress += value!; } } /// /// Add a new action to be performed before application exit /// /// Action to run public static void Add(Action cleanUpCode) { actions.Add(cleanUpCode); } /// /// Run all actions /// /// /// For .Net native /// private static void RunCleanUp() { foreach (Action action in actions) { action(); } } /// /// Run all actions /// /// /// /// /// For win32 API /// private static bool CleanUp(CtrlType sig) { foreach (Action action in actions) { action(); } return false; } [DllImport("Kernel32")] private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add); private delegate bool EventHandler(CtrlType sig); static EventHandler? _handler; enum CtrlType { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT = 1, CTRL_CLOSE_EVENT = 2, CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT = 6 } } }