Windows Vista、7和2008中控制台应用程序的优雅关闭

3

在Windows Vista、7、2008中运行控制台应用程序时,如何处理关闭/ X 按钮?

我发现可以使用SetConsoleControlHandler捕获事件,但是Windows会在一秒钟(或毫秒)后强制终止应用程序。这一秒并不足以让我的应用程序进行清理。


2
“那几秒钟对于我的应用程序来说不足以完成清理。” - 这是什么类型的应用程序?也许你需要这么多时间来清理是合理的,但也许真正的问题在于你需要清理。也许你可以重新审视一下你的设计? - Ed S.
2个回答

2
您可以找出如何检测应用程序想要关闭的方法:

http://geekswithblogs.net/mrnat/archive/2004/09/23/11594.aspx

namespace Detect_Console_Application_Exit2
{
    class Program
    {
        private static bool isclosing = false;
        static void Main(string[] args)
        {
            SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

            Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");
            while (!isclosing) ;

        }

        private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
        {
            // Put your own handler here
            switch (ctrlType)
            {
                case CtrlTypes.CTRL_C_EVENT:
                    isclosing = true;
                    Console.WriteLine("CTRL+C received!");
                    break;

                case CtrlTypes.CTRL_BREAK_EVENT:
                    isclosing = true;
                    Console.WriteLine("CTRL+BREAK received!");
                    break;

                case CtrlTypes.CTRL_CLOSE_EVENT:
                    isclosing = true;
                    Console.WriteLine("Program being closed!");
                    break;

                case CtrlTypes.CTRL_LOGOFF_EVENT:
                case CtrlTypes.CTRL_SHUTDOWN_EVENT:
                    isclosing = true;
                    Console.WriteLine("User is logging off!");
                    break;

            }
            return true;
        }



        #region unmanaged
        // Declare the SetConsoleCtrlHandler function
        // as external and receiving a delegate.

        [DllImport("Kernel32")]
        public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

        // A delegate type to be used as the handler routine
        // for SetConsoleCtrlHandler.
        public delegate bool HandlerRoutine(CtrlTypes CtrlType);

        // An enumerated type for the control messages
        // sent to the handler routine.
        public enum CtrlTypes
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT,
            CTRL_CLOSE_EVENT,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT
        }

        #endregion

    }
}

http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/707e9ae1-a53f-4918-8ac4-62a1eddb3c4a/

作为最后的手段,你可以使用Console.ReadLine()来阻止应用程序关闭...
然后你可以进行清理工作并退出应用程序。
Console.ReadLine()

//your clean up code here

//Exit
System.Windows.Forms.Application.Exit(0)

http://geekswithblogs.net/mtreadwell/archive/2004/06/06/6123.aspx


2

不起作用。奇怪的是,如果用户使用“ctr+c”,应用程序可以防止/延迟关闭(无论是否使用您的解决方案)。但是当用户按下关闭/X按钮时,Windows会强制终止它。 - LostInComputer
不,你说得对。关于这个问题有很多东西,不仅仅是针对C#。真是让人头疼。不过怎么样:让可执行文件在第二个进程中启动自己,使用不同的运行循环(或者有两个可执行文件)。第一个只是一个传递口,将数据传输到第二个,但设置第二个时,使其在控制台被关闭时不会死亡。 - jamie
已接受您的答案。这是一个可能的解决方案。但我将切换到GUI(不那么hackish)。微软破坏了兼容性! - LostInComputer
1
顺便说一句,这就是Visual Studio所做的。当您从命令行运行它时,实际上会调用devenv.com,然后调用devenv.exe。 - jamie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接