C# 如何在命令行应用程序中接收系统关闭或退出事件
本文关键字:系统 出事件 退出 命令行 应用程序 | 更新日期: 2023-09-27 18:34:17
我正在尝试,但到目前为止我发现的一切似乎都以GUI和表单应用程序为中心。那不是我正在使用的。
最终它将是一项服务,但在完成之前,我将它作为普通应用程序运行,问题是如果我意外关闭它,它会让另一个服务挂起长达 30 分钟,并带有不良数据。我虽然很容易添加一个侦听器来捕获正在关闭的应用程序。
但我就是想不通。
在这里,您有一个完美的解决方案来满足您的需求:
在 C# 中检测控制台应用程序退出
该代码检测将关闭应用程序的所有可能事件:
- 控制+C
- 控制+中断 关闭
- 事件(程序的"正常"关闭,使用关闭按钮) 注销
- 事件(使用注销)
- 关机事件(系统关闭)
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
}
}
试试这个:
[编辑] 这是上面发布的链接的修改版本。
注意:如果用户单击红色 X 关闭控制台窗口,则在应用被终止之前,您的响应时间非常有限!如果运行以下程序,请查看消息框在死亡之前显示多长时间。
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
SetConsoleCtrlHandler(ConsoleCtrlCheck, true);
Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");
while (!isclosing)
{
Thread.Sleep(1000);
}
}
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
// Put your own handling 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!");
MessageBox.Show("AHA!");
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
private static bool isclosing;
}
}
如果要在应用程序内处理的事件,
-
如果是视窗服务,
可以使用ServiceBase.OnStop
-
如果是 WCF 服务可以使用 ServiceHost.Closed 事件。服务主机从通信主机继承已关闭(和相关事件)
如果要在单独的应用程序中处理事件,则可以使用 Process.Exited 事件。
var serviceProcesses = Process.GetProcessesByName("service.exe");
if(serviceProcesses != null && serviceProcesses.Length>0)
{
serviceProcesses[0].Exited += OnServiceClosed;
}
AppDomain.CurrentDomain.ProcessExit
事件?