如何使控制台应用程序在关闭时优雅地退出

时间:2021-01-27 22:10:48

I wrote this little program to demonstrate the point of the question:

我写了这个小程序来说明问题的要点:

using System;
using System.IO;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        using (var disp = new MyDisp())
        {
            using (var ewhLocalExit = new EventWaitHandle(false, EventResetMode.ManualReset))
            {
                Console.WriteLine("Enter Ctrl+C to terminate the app.");
                Console.CancelKeyPress += (_, e) =>
                {
                    e.Cancel = true;
                    ewhLocalExit.Set();
                };
                ewhLocalExit.WaitOne();
            }
        }
        File.AppendAllText("Log.txt", "Terminated.\n");
    }
}


class MyDisp : IDisposable
{
    public MyDisp()
    {
        File.AppendAllText("Log.txt", "Started.\n");
    }

    public void Dispose()
    {
        File.AppendAllText("Log.txt", "Disposed.\n");
    }
}

When I run it and press Ctrl+C, I see "Started.Disposed.Terminated." in Log.txt
When I run it and close it with the mouse, I see only "Started."

当我运行它并按下Ctrl+C时,我看到“开始。处理。终止。”在日志中。txt当我运行它并用鼠标关闭它时,我只看到“启动”。

How do I make exit gracefully, so that I at least could see "Disposed." ?

我如何优雅地退出,以便至少能看到“处置”。吗?

2 个解决方案

#1


2  

You can use DLLImport to import SetConsoleControlHandler and use it to register an event handler for the closed event (and others), here's an example snippet that shows it working (it will write closed in Log.txt whem you click the X to close the console):

您可以使用DLLImport导入setcomfort econtrolhandler并使用它为关闭事件(和其他事件)注册一个事件处理程序,这里有一个示例片段显示它正在工作(它将在日志中写入closed)。点击X键关闭控制台):

class Program
{
    [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
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
            File.AppendAllText(@"Log.txt", "closed");

        return true;
    }

    private static void Main(string[] args)
    {
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
        Console.WriteLine("Close me");
        Console.ReadLine();
    }
}

Source

#2


2  

When you close your console app with the mouse by clicking the X button you are asking to have the process killed.

当您用鼠标单击X按钮关闭控制台应用程序时,您要求终止进程。

The Wi32 api has a SetConsoleControlHandler that allows you to specify a handler for when various things happen. If the handler is called with CTRL_CLOSE_EVENT then you know that someone is trying to kill your application.

Wi32 api有一个setcomfort econtrolhandler,它允许您为各种事情发生时指定一个处理程序。如果用CTRL_CLOSE_EVENT调用处理程序,那么您就知道有人试图杀死您的应用程序。

There's an example of how to use this API here

这里有一个如何使用这个API的示例

#1


2  

You can use DLLImport to import SetConsoleControlHandler and use it to register an event handler for the closed event (and others), here's an example snippet that shows it working (it will write closed in Log.txt whem you click the X to close the console):

您可以使用DLLImport导入setcomfort econtrolhandler并使用它为关闭事件(和其他事件)注册一个事件处理程序,这里有一个示例片段显示它正在工作(它将在日志中写入closed)。点击X键关闭控制台):

class Program
{
    [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
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
            File.AppendAllText(@"Log.txt", "closed");

        return true;
    }

    private static void Main(string[] args)
    {
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
        Console.WriteLine("Close me");
        Console.ReadLine();
    }
}

Source

#2


2  

When you close your console app with the mouse by clicking the X button you are asking to have the process killed.

当您用鼠标单击X按钮关闭控制台应用程序时,您要求终止进程。

The Wi32 api has a SetConsoleControlHandler that allows you to specify a handler for when various things happen. If the handler is called with CTRL_CLOSE_EVENT then you know that someone is trying to kill your application.

Wi32 api有一个setcomfort econtrolhandler,它允许您为各种事情发生时指定一个处理程序。如果用CTRL_CLOSE_EVENT调用处理程序,那么您就知道有人试图杀死您的应用程序。

There's an example of how to use this API here

这里有一个如何使用这个API的示例