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


    转自: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.
  • 相关阅读:
    ADO.NET 根据实体类自动生成添加修改语句仅限Oracle使用
    C# 实体对象作为参数统一去除空格
    jQuery 前端复选框 全选 反选 下拉菜单联动
    C# 后台服务器端 Get 请求函数封装
    服务器404错误页面
    vue 封装公用函数
    Vue 生命周期
    Oracle 查看表结构
    ubuntu源配置
    外观(Facade)模式
  • 原文地址:https://www.cnblogs.com/yuanbao/p/1204107.html
Copyright © 2020-2023  润新知