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

控制台程序足够简洁,但是,经常会点错而误关闭。而且,如果系统关闭,或者用户注销,这时候任务还没完成的话,前面的运算电费就白出了。

有没有办法和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.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值