控制台程序在服務器後台運行時,可能因異常、用戶關閉窗口、系統關機等被強制終止。通過 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 秒)。ServiceBase.OnStop。