.NET C#控制台程序如何检测系统关机并延迟关机实现优雅退出
C#控制台程序拦截Windows系统关机实现方案
问题根因说明
你之前尝试的两个事件无法触发的原因如下:
Application.ApplicationExit属于System.Windows.Forms命名空间,仅WinForm应用程序会触发,控制台程序不加载窗体消息循环,自然不会触发。AppDomain.CurrentDomain.ProcessExit仅在进程正常退出前触发,且默认执行时间限制为2秒,超时会被系统强制终止,关机场景下这个事件往往还没触发进程就被结束了。
可行实现方案
要实现和记事本一致的阻塞关机效果,需要调用Windows原生API实现两个核心逻辑:注册控制台关机事件监听、设置进程关机优先级允许阻塞。完整可运行代码示例如下:
using System; using System.Runtime.InteropServices; using System.Threading; class ShutdownHandler { // 控制台控制事件类型:关机事件 private const int CTRL_SHUTDOWN_EVENT = 6; // 关机参数:禁止系统自动重试杀进程 private const int SHUTDOWN_NORETRY = 1; // 控制台控制回调委托 private delegate bool ConsoleCtrlDelegate(int ctrlType); // 导入Win32 API:注册控制台控制回调 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handler, bool add); // 导入Win32 API:设置进程关机优先级和行为 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetProcessShutdownParameters(uint level, uint flags); // 测试用标记:任务是否正在运行、是否收到关机通知 private static bool _taskRunning = true; private static bool _shutdownReceived = false; static void Main(string[] args) { // 1. 设置进程关机参数:最高应用级优先级,禁止系统自动杀进程重试 SetProcessShutdownParameters(0x3FF, SHUTDOWN_NORETRY); // 2. 注册控制台控制回调,监听系统事件 SetConsoleCtrlHandler(ConsoleCtrlHandlerCallback, true); Console.WriteLine("程序运行中,模拟长时间测试任务..."); // 模拟长时间运行的测试任务 while (_taskRunning) { Thread.Sleep(1000); // 收到关机通知后执行收尾逻辑 if (_shutdownReceived) { Console.WriteLine("检测到系统关机,开始保存测试数据、发送通知邮件..."); // 这里替换为你自己的数据保存、邮件发送逻辑 Thread.Sleep(5000); // 模拟5秒的收尾操作,实际时长按需求调整 Console.WriteLine("收尾完成,允许系统关机"); _taskRunning = false; } } } private static bool ConsoleCtrlHandlerCallback(int ctrlType) { if (ctrlType == CTRL_SHUTDOWN_EVENT) { _shutdownReceived = true; // 返回true表示已接管该事件,系统会等待进程退出,实现阻塞关机效果 return true; } // 其他事件(如关闭控制台窗口、用户登出等)交给系统默认处理 return false; } }
注意事项
- Win10及以上系统默认的关机阻塞超时为5分钟,超过该时长系统会强制杀掉所有进程执行关机。如果你的单轮测试任务执行时长超过5分钟,建议收到关机通知后优先保存中间测试快照,再主动退出进程,避免数据丢失。
- 如果后续将程序改造为Windows服务,需要替换为服务专属的关机处理逻辑:设置
ServiceBase.CanShutdown = true,重写OnShutdown方法即可实现相同的关机拦截效果。
内容的提问来源于stack exchange,提问作者Curtis
相关产品推荐
相关产品推荐

