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
+ }
+ }
+}