首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 捕獲控制台關閉事件:SetConsoleCtrlHandler 實現優雅退出

     編輯:關於C語言

控制台程序在服務器後台運行時,可能因異常、用戶關閉窗口、系統關機等被強制終止。通過 P/Invoke 調用 kernel32.dll.SetConsoleCtrlHandler 註冊回調,可在進程退出前執行日誌記錄、資源釋放等清理工作。

完整代碼

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;

namespace XMLpusher
{
    public delegate bool ConsoleCtrlDelegate(int ctrlType);

    class Program
    {
        [DllImport("kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handler, bool add);

        private const int CTRL_C_EVENT = 0;
        private const int CTRL_BREAK_EVENT = 1;
        private const int CTRL_CLOSE_EVENT = 2;      // 用戶關閉窗口
        private const int CTRL_LOGOFF_EVENT = 5;     // 用戶註銷
        private const int CTRL_SHUTDOWN_EVENT = 6;   // 系統關機

        static void Main(string[] args)
        {
            ConsoleCtrlDelegate handler = new ConsoleCtrlDelegate(HandlerRoutine);
            bool ok = SetConsoleCtrlHandler(handler, true);
            Console.WriteLine(ok ? "Handler registered" : "Registration failed");

            Console.WriteLine("Running... Press Ctrl+C or close window to test.");
            Console.ReadLine(); // 保持運行
        }

        private static bool HandlerRoutine(int ctrlType)
        {
            switch (ctrlType)
            {
                case CTRL_CLOSE_EVENT:
                case CTRL_LOGOFF_EVENT:
                case CTRL_SHUTDOWN_EVENT:
                    // 執行清理邏輯:寫日誌、關閉連接等
                    for (int i = 0; i < 10; i++)
                    {
                        Console.WriteLine($"Shutdown cleanup step {i}");
                        Thread.Sleep(500);
                    }
                    break;
            }
            return false; // false 讓系統繼續默認處理(關閉進程)
        }
    }
}

關鍵說明

  • 回調返回 false 表示不攔截事件,系統將繼續終止進程;返回 true 可阻止關閉(僅對 CTRL_C/BREAK 有效)。
  • CTRL_CLOSE_EVENT、CTRL_LOGOFF_EVENT、CTRL_SHUTDOWN_EVENT **無法阻止**,只能搶時間做清理(系統給予有限時間,約 5-10 秒)。
  • 長時間清理任務建議啟動單獨線程,主線程快速返回。
  • 若需在 Windows 服務中使用,請改用 ServiceBase.OnStop。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved