截獲控制台程序關閉事件(SetConsoleCtrlHandler)


    最近控制台程序中需要捕獲控制台關閉事件,在用戶關閉的時候進行某些操作,找了一大圈發現了一個方法,通過調用WIN32 API SetConsoleCtrlHandler方法來實現,具體代碼如下:

 1 using System;  2 using System.Windows.Forms;  3 using System.Diagnostics;  4 using System.Runtime.InteropServices;  5 
 6 namespace ConsoleColsed  7 {  8   public delegate bool ConsoleCtrlDelegate(int ctrlType);  9   class Program 10  { 11     [DllImport("kernel32.dll")] 12     private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add); 13     //當用戶關閉Console時,系統會發送次消息
14     private const int CTRL_CLOSE_EVENT = 2; 15     //Ctrl+C,系統會發送次消息
16     private const int CTRL_C_EVENT = 0; 17     //Ctrl+break,系統會發送次消息
18     private const int CTRL_BREAK_EVENT = 1; 19     //用戶退出(注銷),系統會發送次消息
20     private const int CTRL_LOGOFF_EVENT = 5; 21     //系統關閉,系統會發送次消息
22     private const int CTRL_SHUTDOWN_EVENT = 6; 23 
24     static void Main(string[] args) 25  { 26        Program cls = new Program(); 27        
28  } 29     public Program() 30  { 31       ConsoleCtrlDelegate consoleDelegete = new ConsoleCtrlDelegate(HandlerRoutine); 32 
33       bool bRet = SetConsoleCtrlHandler(consoleDelegete, true); 34       if (bRet == false) //安裝事件處理失敗
35  { 36          Debug.WriteLine("error"); 37  } 38       else
39  { 40          Console.WriteLine("ok"); 41  Console.Read(); 42  } 43  } 44 
45     private static bool HandlerRoutine(int ctrlType) 46  { 47       switch(ctrlType) 48  { 49         case CTRL_C_EVENT:// Ctrl+C 事件 50           Console.WriteLine("-- CTRL_C_EVENT --"); 51         break; 52         case CTRL_BREAK_EVENT: 53           Console.WriteLine("-- CTRL_BREAK_EVENT --"); 54         break; 55         case CTRL_CLOSE_EVENT://用戶點 X 關閉事件 56           Console.WriteLine("-- CTRL_CLOSE_EVENT --"); 57         break; 58         case CTRL_LOGOFF_EVENT: 59         break; 60         case CTRL_SHUTDOWN_EVENT://系統關閉事件 61         break; 62  } 63     //return true;//表示阻止響應系統對該程序的操作
64     return false;//忽略處理,讓系統進行默認操作
65  } 66  } 67 }   

    不過這個方法我在運用的時候遇到了這樣的一個問題:對“::Invoke”類型的已垃圾回收委托進行了回調。這可能會導致應用程序崩潰、損壞和數據丟失。即使將項目 屬性-》生成-》忽略不安全代碼  這個選項打勾,仍然出現這個錯誤,除非用Release模式編譯運行。Debug模式或者直接運行EXE文件都會報錯,在網上查找了一圈找到一個解決方法,那就是先聲明一個回調委托的成員變量,這樣可以防止被垃圾回收。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM