阅读文章

控制‘控制台应用程序’的关闭操作

[日期:2008-03-18] 来源:  作者: [字体: ]

     控制台程序足够简洁,但是,经常会点错而误关闭。而且,如果系统关闭,或者用户注销,这时候任务还没完成的话,前面的运算电费就白出了。
  
  有没有办法和WinForm一样,对控制台的退出事件进行控制呢?有的!
  
  引入下面的函数
  1 public delegate bool HandlerRoutine(int dwCtrlType);
  2
  3 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  4 public static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool add);
  委托HandlerRoutine,就是把函数的指针传递给系统API函数SetConsoleCtrlHandler。这是个典型的回调函数。
  
  然后在Main方法中调用
   Program p = new Program();
   if (!SetConsoleCtrlHandler(p.HandlerRoutineMethod, true))
   {
   Console.WriteLine("Unable to install event handler!\n");
   }
   const int CTRL_C_EVENT = 0;
   const int CTRL_BREAK_EVENT = 1;
   const int CTRL_CLOSE_EVENT = 2;
   const int CTRL_LOGOFF_EVENT = 5;
   const int CTRL_SHUTDOWN_EVENT = 6;
  
   public bool HandlerRoutineMethod(int dwCtrlType)
   {
   Console.WriteLine(dwCtrlType.ToString());
   switch (dwCtrlType)
   {
   case CTRL_C_EVENT:
   return true;
   case CTRL_BREAK_EVENT:
   return false;
   case CTRL_CLOSE_EVENT:
   Console.WriteLine("确实要退出程序么?如果需要退出,请输入'exit'。");
   return true;
   case CTRL_LOGOFF_EVENT:
   //用户退出
   return false;
   case CTRL_SHUTDOWN_EVENT:
   //系统关闭
   return false;
   }
   return true;
   }
  HandlerRoutineMethod函数,就是系统的真实回调。如果返回的结果为false,则程序关闭,否则,不会关闭。
  这里只在CTRL_BREAK_EVENT(按下Ctrl+Break),CTRL_LOGOFF_EVENT用户退出,和系统关闭 CTRL_SHUTDOWN_EVENT,事件时,调用了return false,也就是说,这个时候会关闭。但是在关闭之前我们可以做一些操作。
  
  试想这样的情况,这个任务可能需要运行很长时间,要能在程序关闭的时候有个保存当前进度的方法,那么就可以采用以上操作了。
  
  来看个完整的代码
  
   1 class Program
   2 {
   3 static void Main(string[] args)
   4 {
   5 Program p = new Program();
   6 if (!SetConsoleCtrlHandler(p.HandlerRoutineMethod, true))
   7 {
   8 Console.WriteLine("无法注册系统事件!\n");
   9 }
  10
  11 while (true)
  12 {
  13 string s = Console.ReadLine();
  14 if (s == "exit")
  15 GenerateConsoleCtrlEvent(p.CTRL_BREAK_EVENT, 0);
  16 }
  17 }
  18
  19 const int CTRL_C_EVENT = 0;
  20 const int CTRL_BREAK_EVENT = 1;
  21 const int CTRL_CLOSE_EVENT = 2;
  22 const int CTRL_LOGOFF_EVENT = 5;
  23 const int CTRL_SHUTDOWN_EVENT = 6;
  24
  25 public bool HandlerRoutineMethod(int dwCtrlType)
  26 {
  27 Console.WriteLine(dwCtrlType.ToString());
  28 switch (dwCtrlType)
  29 {
  30 case CTRL_C_EVENT:
  31 return true;
  32 case CTRL_BREAK_EVENT:
  33 Save();
  34 return false;
  35 case CTRL_CLOSE_EVENT:
  36 Console.WriteLine("确实要退出程序么?如果需要退出,请输入'exit'。");
  37 return true;
  38 case CTRL_LOGOFF_EVENT:
  39 //用户退出
  40 Save();
  41 return false;
  42 case CTRL_SHUTDOWN_EVENT:
  43 //系统关闭
  44 Save();
  45 return false;
  46 }
  47 return true;
  48 }
  49
  50 void Save()
  51 {
  52 //保存当前进度
  53 }
  54
  55 public delegate bool HandlerRoutine(int dwCtrlType);
  56
  57 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  58 public static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool add);
  59
  60 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  61 public static extern bool GenerateConsoleCtrlEvent(int code, int value);
  62 }
  先 是用SetConsoleCtrlHandler方法,设置了HandlerRoutineMethod为他的回调函数。那么当有事件过来的时候,会先调用这个方法。这个方法return false,则窗体关闭,true,则窗体不关闭。
  
  
  GenerateConsoleCtrlEvent方法是通知系统事件的。我们这里假设,只有用户输入exit,或者按Ctrl+Break的时候程序退出。对于用户退出和系统关闭,只是保存当前进度。
  
  在while 循环中,如果用户输入exit命令,则通知系统调用回调函数HandlerRoutineMethod,调用的事件是Ctrl+Break。
  
  现在控制台是不是比以前好用了很多呢?:)
  
  全文完。 by yurow.  


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:【翻译】Lambda表达式学习
下一篇:实例讲解IE8新特性之webSlices
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款