diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 2799afe6..910fbdff 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -362,6 +362,7 @@ + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 23b0bde4..27552182 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -150,6 +150,15 @@ namespace MinecraftClient { RequestPassword(); } + + // Setup exit cleaning code + ExitCleanUp.Add(delegate () + { + // Do NOT use Program.Exit() as creating new Thread cause program to freeze + if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } + if (offlinePrompt != null) { offlinePrompt.Abort(); offlinePrompt = null; ConsoleIO.Reset(); } + if (Settings.playerHeadAsIcon) { ConsoleIcon.revertToMCCIcon(); } + }); startupargs = args; diff --git a/MinecraftClient/WinAPI/ExitCleanUp.cs b/MinecraftClient/WinAPI/ExitCleanUp.cs new file mode 100644 index 00000000..c3a62f8e --- /dev/null +++ b/MinecraftClient/WinAPI/ExitCleanUp.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +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 List actions = new List(); + + 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 + Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e) + { + RunCleanUp(); + }; + } + } + + /// + /// 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(ConsoleCtrlHandler handler, bool add); + private delegate bool ConsoleCtrlHandler(CtrlType sig); + private static ConsoleCtrlHandler _handler; + + enum CtrlType + { + CTRL_C_EVENT = 0, + CTRL_BREAK_EVENT = 1, + CTRL_CLOSE_EVENT = 2, + CTRL_LOGOFF_EVENT = 5, + CTRL_SHUTDOWN_EVENT = 6 + } + } +}