C#控制台应用程序Environment.Exit(0)未被识别为关闭事件

时间:2015-01-26 17:07:30

标签: c# event-handling console-application application-shutdown

我有一个简单的库,可以覆盖控制台的关闭事件,以便在关闭之前完成各种任务。只要用户或外部程序关闭控制台(ctrl + C,关闭窗口等),这就有效,但是,当控制台应用程序使用Environment.Exit()时,它会关闭而不会被识别为关闭事件之一。

以下是关闭处理程序的代码:

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

应用程序本身使用关闭处理程序(ConsoleHandler),如下所示:

    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();
        }
    }

我认为ConsoleHandler类中的CtrlType枚举是罪魁祸首,但我似乎无法弄清楚缺少哪些值。

有什么想法吗?

1 个答案:

答案 0 :(得分:-1)

退出不会执行正常关机。退出类似于拉动PC的电源线,而start-&gt; shutdown是正常的,并通知运行的应用程序系统正在关闭。

发出“退出”命令时,不会向正在运行的应用程序发送任何消息。您需要改为使用application.Shutdown。

请参阅what's difference between Environment.Exit() and Application.Shutdown()?

编辑:抱歉没有注意到它是一个控制台应用程序。您可以尝试处理AppDomain.ProcessExit事件。但说实话,我不认为这个事件有效。众所周知,如果发出粗鲁的退出命令(如结束任务),则不会触发此事件。退出是非常粗鲁的。