有没有办法和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);
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 " );
}
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 ;
}
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 }
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.