我写了这个小程序来证明问题的重点:
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");
}
}
当我运行它并按Ctrl + C时,我看到“Started.Disposed.Terminated”。在Log.txt中 当我运行它并用鼠标关闭它时,我只看到“已启动”。
如何优雅地退出,这样我至少可以看到“Disposed”。 ?
答案 0 :(得分:2)
当您通过单击X
按钮关闭控制台应用程序时,您要求让该进程终止。
Wi32 api有SetConsoleControlHandler,允许您指定处理各种事件的处理程序。如果使用CTRL_CLOSE_EVENT调用处理程序,那么您就知道有人试图杀死您的应用程序。
有一个如何使用此API here
的示例答案 1 :(得分:2)
您可以使用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();
}
}