From c4516a3444c368fbf604aec636f80873276c4f8d Mon Sep 17 00:00:00 2001 From: Alex Fort Date: Tue, 9 Nov 2010 15:22:49 -0500 Subject: [PATCH] Add support for the CancelKeyPress event on Windows Adds a call to the Win32 function SetConsoleCtrlHandler for Windows, which adds the DoWindowsConsoleCancelEvent wrapper for DoConsoleCancelEvent to the Ctrl-C handler when an event handler is added, and removes the handler once all event handlers are removed. --- mcs/class/corlib/System/Console.cs | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/mcs/class/corlib/System/Console.cs b/mcs/class/corlib/System/Console.cs index 9457016a431d..8b68f4f505f3 100644 --- a/mcs/class/corlib/System/Console.cs +++ b/mcs/class/corlib/System/Console.cs @@ -44,11 +44,26 @@ public static class Console #if !NET_2_1 private class WindowsConsole { + public static bool ctrlHandlerAdded = false; + private delegate bool WindowsCancelHandler (int keyCode); + private static WindowsCancelHandler cancelHandler = new WindowsCancelHandler (DoWindowsConsoleCancelEvent); + [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] private static extern int GetConsoleCP (); [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] private static extern int GetConsoleOutputCP (); + [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] + private static extern bool SetConsoleCtrlHandler (WindowsCancelHandler handler, bool addHandler); + + // Only call the event handler if Control-C was pressed (code == 0), nothing else + private static bool DoWindowsConsoleCancelEvent (int keyCode) + { + if (keyCode == 0) + DoConsoleCancelEvent (); + return keyCode == 0; + } + [MethodImpl (MethodImplOptions.NoInlining)] public static int GetInputCodePage () { @@ -60,6 +75,18 @@ public static int GetOutputCodePage () { return GetConsoleOutputCP (); } + + public static void AddCtrlHandler () + { + SetConsoleCtrlHandler (cancelHandler, true); + ctrlHandlerAdded = true; + } + + public static void RemoveCtrlHandler () + { + SetConsoleCtrlHandler (cancelHandler, false); + ctrlHandlerAdded = false; + } } #endif internal static TextWriter stdout; @@ -682,12 +709,22 @@ public static event ConsoleCancelEventHandler CancelKeyPress { ConsoleDriver.Init (); cancel_event += value; + + if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded) + WindowsConsole.AddCtrlHandler(); } remove { if (ConsoleDriver.Initialized == false) ConsoleDriver.Init (); cancel_event -= value; + + if (cancel_event == null && Environment.IsRunningOnWindows) + { + // Need to remove our hook if there's nothing left in the event + if (WindowsConsole.ctrlHandlerAdded) + WindowsConsole.RemoveCtrlHandler(); + } } }