zoukankan      html  css  js  c++  java
  • 控制‘控制台应用程序’的关闭操作

    转自:http://www.cnblogs.com/birdshover/archive/2008/03/18/1110138.html

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

    有没有办法和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_EVENT0);
    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.
  • 相关阅读:
    fn project 试用之后的几个问题的解答
    fn project 扩展
    fn project 生产环境使用
    fn project 对象模型
    fn project AWS Lambda 格式 functions
    fn project 打包Function
    fn project Function files 说明
    fn project hot functions 说明
    fn project k8s 集成
    fn project 私有镜像发布
  • 原文地址:https://www.cnblogs.com/yuanbao/p/1204107.html
Copyright © 2011-2022 走看看