0

我有一个简单的库,它覆盖控制台的关闭事件以在关闭之前完成各种任务。这在用户或外部程序关闭控制台(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 枚举是罪魁祸首,但我似乎无法弄清楚缺少哪些值。

有任何想法吗?

4

1 回答 1

0

Exit 不会执行正常关闭。Exit 类似于您拔掉 PC 的电源线,而 start->shutdown 是优雅的,它会通知正在运行的应用程序系统正在关闭。

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

看看Environment.Exit() 和 Application.Shutdown() 有什么区别?

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

于 2015-01-26T17:18:24.813 回答