如何使控制台应用程序在关闭时正常退出

boh*_*nko 6 .net c# winapi

我写了这个小程序来证明问题的重点:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行它并按Ctrl + C时,我看到"Started.Disposed.Terminated".在Log.txt中
当我运行它并用鼠标关闭它时,我只看到"已启动".

如何优雅地退出,这样我至少可以看到"Disposed".?

Rui*_*Rui 4

您可以使用 DLLImport 导入 SetConsoleControlHandler 并使用它为关闭事件(和其他事件)注册事件处理程序,这里有一个示例片段,显示它的工作原理(当您单击 X 关闭控制台时,它将在 Log.txt 中写入关闭) ):

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

来源