You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 14:27:02