summaryrefslogtreecommitdiff
path: root/docs/service/console_event_handling.txt
blob: 2944ed1da23071c325f4fd25798dd8b8fcdea274 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

Introduction

   Everyone programs console applications one time or the other. This
   programming is more prevalent when people are learning to program,
   especially while learning the DOS based C/C++ programming. However,
   when one migrates to Windows programming, console application
   development takes a back seat. But the Win32 console development holds
   an important place, especially when the Win32 API contains a good
   amount of API dedicated to console application development. If you have
   noticed, even VC++, and latest development technologies like C#, also
   supports console project development. Console applications are good
   candidates for testing the core functionality of your Windows
   application without the unnecessary overhead of a GUI.

   But there's always been a sense of helplessness in regard to how to
   know when certain system related events have occurred, like when user
   if logging off, or the system is being shutdown, or handling
   control+break or control+C keyboard events, etc. For a Windows based
   application, getting to know when such events occur is no problem since
   they are having a message queue assigned to them that is polled, and
   assuming that the concerned event is programmed for, it can be handled
   pretty easily. But this isn't the case with a console application that
   has no concept of a message queue.

   This article intends to discuss how you can handle all kinds of
   console-based events in any console application. Once you have gone
   through it, you will see for yourself how trivial this seemingly
   helpless task is :)

Setting Console Traps

   The first step in handling console application events is to setup an
   even trap, technically referred to as installing an event handler. For
   this purpose, we utilize the SetConsoleCtrlHandler Win32 API that is
   prototyped as shown below:
   [minus.gif] Collapse
BOOL SetConsoleCtrlHandler(
    PHANDLER_ROUTINE HandlerRoutine, // handler function

    BOOL Add // add or remove handler

    );

   The HandlerRoutine parameter is a pointer to a function that has the
   following prototype:
   [minus.gif] Collapse
BOOL WINAPI HandlerRoutine(
    DWORD dwCtrlType   //  control signal type

);

   All the HandlerRoutine takes is a DWORD parameter that tells what
   console event has taken place. The parameter can take the following
   values:
     * CTRL_C_EVENT - occurs when the user presses CTRL+C, or when it is
       sent by the GenerateConsoleCtrlEvent API.
     * CTRL_BREAK_EVENT - occurs when the user presses CTRL+BREAK, or when
       it is sent by the GenerateConsoleCtrlEvent API.
     * CTRL_CLOSE_EVENT - occurs when attempt is made to close the
       console, when the system sends the close signal to all processes
       associated with a given console.
     * CTRL_LOGOFF_EVENT - occurs when the user is logging off. One cannot
       determine, however, which user is logging off.
     * CTRL_SHUTDOWN_EVENT - occurs when the system is being shutdown, and
       is typically sent to services.

   Upon receiving the event, the HandlerRoutine can either choose to do
   some processing, or ignore the event. If the routine chooses not to
   handle the event, it should return FALSE, and the system shall then
   proceed to the next installed handler. But incase the routine does
   handle the event, it should then return TRUE, after doing all the
   processing it requires. The CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT and
   CTRL_SHUTDOWN_EVENT are typically used to perform any cleanup that is
   required by the application, and then call the ExitProcess API. Thus,
   the system has has some timeouts associated with these three events,
   which is 5 seconds for CTRL_CLOSE_EVENT, and 20 seconds for the other
   two. If the process doesn't respond within the timeout period, Windows
   shall then proceed to display the End Task dialog box to the user. If
   the user proceeds to end the task, then the application will not have
   any opportunity to perform cleanup. Thus, any cleanup that is required
   should complete well within the timeout period. Below is an
   exemplification of the handler routine:
   [minus.gif] Collapse
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    char mesg[128];

    switch(CEvent)
    {
    case CTRL_C_EVENT:
        MessageBox(NULL,
            "CTRL+C received!","CEvent",MB_OK);
        break;
    case CTRL_BREAK_EVENT:
        MessageBox(NULL,
            "CTRL+BREAK received!","CEvent",MB_OK);
        break;
    case CTRL_CLOSE_EVENT:
        MessageBox(NULL,
            "Program being closed!","CEvent",MB_OK);
        break;
    case CTRL_LOGOFF_EVENT:
        MessageBox(NULL,
            "User is logging off!","CEvent",MB_OK);
        break;
    case CTRL_SHUTDOWN_EVENT:
        MessageBox(NULL,
            "User is logging off!","CEvent",MB_OK);
        break;

    }
    return TRUE;
}

   Now that we have seen how the handler routine works, lets see how to
   install the handler. To do so, as mentioned earlier in the article, we
   use the SetConsoleCtrlHandler API as shown below:
   [minus.gif] Collapse
if (SetConsoleCtrlHandler(
    (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE)
{
    // unable to install handler...

    // display message to the user

    printf("Unable to install handler!\n");
    return -1;
}

   The first parameter is a function pointer of the type PHANDLER_ROUTINE,
   whose prototype has been discussed earlier. The second parameter, if
   set to TRUE, tries installing the handler, and if set to FALSE,
   attempts the un-installation. If either attempts are successful, the
   return value is TRUE. Otherwise FALSE is returned.

   So, that's all there is to handling the console application events.
   After handler is installed, your application will receive the events as
   and by they come, and when the execution is about to be terminated, the
   handler maybe un-installed. Pretty easy, eh :) ?

License

   This article has no explicit license attached to it but may contain
   usage terms in the article text or the download files themselves. If in
   doubt please contact the author via the discussion board below.

   A list of licenses authors might use can be found [232]here

About the Author

   [233]Kumar Gaurav Khanna

   I hold Early Acheiver in MCSE 2000, MCSE NT 4.0, MCP+I, and actively
   involved in programming using C/C++, .NET framework, C#, Win32 API, VB,
   ASP and MFC.
   I also have various publications to my credit at MSDN Online Peer
   Journal, Windows Developer Journal (http://www.wdj.com/), Developer 2.0
   (http://www.developer2.com/), and PC Quest (http://www.pcquest.com/).
   Occupation: Web Developer
   Location:   United States United States

Other popular Win32/64 SDK & OS articles:

     * [234]Lock Windows Desktop
       Restricting Windows access by hiding desktop windows and disabling
       special keys.
     * [235]Win32++: A Simple Alternative to MFC
       A simple Windows Framework that beginners and intermediate
       programmers can use as an alternative to MFC. It makes learning to
       program for Windows easier.
     * [236]Use member functions for C-style callbacks and threads - a
       general solution
       The article shows a general solution to redirect any C-style
       callback into a member function using adapter objects
     * [237]Windows 2000 Junction Points
       Explains how reparse points are used to create filesystem links
     * [238]Message Cracker Wizard for Win32 SDK Developers
       A ClassWizard-like helper tool for using WINDOWSX.H message
       crackers.

   IFRAME: [239]console_event_handling.aspx_files/ServeHTML_002.html

   [240]Article Top
   [241]Sign Up to vote for this article
   Your reason for this vote:
   ____________________________________________________________
   ____________________________________________________________
   ____________________________________________________________
   ____________________________________________________________
   ____________________________________________________________

   IFRAME: [242]console_event_handling.aspx_files/ServeLinks.html

   You must [243]Sign In to use this message board.
   FAQ  [244]FAQ  Noise Tolerance[Medium...] Search  [245]Search Messages
   Set Options
     Layout[Normal...............]   Per page[25]
     Msgs 1 to 11 of 11 (Total in Forum: 11) ([246]Refresh) FirstPrevNext
   General [247]Lock computer member [248]Deepak Kumar Singh 3:04 7 Dec
   '04
   Hi!
   Good article. In case we want to handle the event of user locking the
   computer (Ctl+Alt+DEL then 'Lock Computer') then how do we do that?
   Lets say my application is a windows service!
   Thanks,
   Deepak
   [249]Sign In·[250]View Thread·[251]PermaLink
   General [252]Re: Lock computer member [253]Deepak Kumar Singh 20:13 7
   Dec '04
   Hi!
   I got the answer my self. Unless you are really working with console
   based applications, you should rather work with 'Winlogon Notification
   Packages'. But they are not supported on Win NT and lower.
   For more info see:
   [254]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/s
   ecauthn/security/winlogon_notification_packages.asp[[255]^]
   -- Deepak
   [256]Sign In·[257]View Thread·[258]PermaLink
   General [259]Nice, but ... suss Anonymous 16:12 9 Apr '03
   it only works if a console window exists. If you use it within a gui
   application, you won't receive any messages. Furthermore it does not
   work with Win95/98 and WinME. Or did anyone made other experiences?
   [260]Sign In·[261]View Thread·[262]PermaLink 1.00/5 (2 votes)
   General [263]MessageBox member [264]Sarwan Aggarwal 17:18 27 Aug '03
   Hi:
   I like that MessageBox example code:
   int MessageBox(0, char *msg, char *title, int type);
   Which header do I include? My VC++ 6.0 does not recognize
   MessageBox().
   Thanks.
   Sarwan
   Sarwan K. Aggarwal
   [265]Sign In·[266]View Thread·[267]PermaLink
   General [268]Re: MessageBox member [269]yjip 0:26 15 Nov '03
   you can look msdn ,that there are information sdk very much!
   if you not see ,you can keep in touch with me my emailaddress :
   4915259@163.com
   ok
   yjip
   [270]Sign In·[271]View Thread·[272]PermaLink
          General     [273]How can I pass control-break to console application?
   member [274]Slimer 23:42 30 Mar '03
   How can I pass control-break to console application?
   [275]Sign In·[276]View Thread·[277]PermaLink 1.50/5 (2 votes)
   General [278]Argh! suss Anonymous 20:34 18 Feb '03
   Alright, the author mentions that when the program is about to be
   closed, the handler is unisntalled... This may have something to do
   with an issue I'm having...
   I have a program that uses AllocConsole() to get a console. Most of the
   entire program is all WinAPI, and the console is only used for quickly
   adding large amounts of data. So I launch my app, it spawns a console,
   the console is made into a child window... Now, if you click close, the
   whole app goes down. Ctrl-C and the same...
   I installed an insane amount of message handlers before learning about
   the Console Control Handler. (Duh!)... Now that I'm using the control
   handler to try and trap the events, the Ctrl-C problem is taken care
   of. But no matter what, whenever you close it, the whole program goes
   down. How do you stop this? I'd prefer the console just get freed
   instead of killing the whole app!
   Dead
   [279]Sign In·[280]View Thread·[281]PermaLink 3.43/5 (4 votes)
   General [282]Re: Argh! suss Anonymous 0:58 4 May '04
   in each of the console event handlers, you could call FreeConsole(),
   This seemed to work for me, the only thing was there was a slight delay
   between the close button being clicked and the console window being
   destroyed.
   [283]Sign In·[284]View Thread·[285]PermaLink 2.00/5 (1 vote)
   General [286]how can i get the source code! suss Anonymous 23:26 14 Nov
   '02
   This is a wonderful article but how can I get the source code. I
   download it but I can not unzip it.Kindly send me the code. Thanks.
   [287]Sign In·[288]View Thread·[289]PermaLink 1.00/5 (1 vote)
   General [290]Sameple code Re: how can i get the source code! member
   [291]SMuddasu 9:29 15 Nov '02
   BOOL CtrlHandler(DWORD fdwCtrlType)
   {
   switch (fdwCtrlType)
   {
   // Handle the CTRL+C signal.
   case CTRL_C_EVENT:
   Beep(1000, 1000);
   return TRUE;
   // CTRL+CLOSE: confirm that the user wants to exit.
   case CTRL_CLOSE_EVENT:
   return TRUE;
   // Pass other signals to the next handler.
   case CTRL_BREAK_EVENT:
   case CTRL_LOGOFF_EVENT:
   case CTRL_SHUTDOWN_EVENT:
   default:
   return FALSE;
   }
   }
   void main(void)
   {
   BOOL fSuccess;
   fSuccess = SetConsoleCtrlHandler(
   (PHANDLER_ROUTINE) CtrlHandler, // handler function
   TRUE); // add to list
   if (! fSuccess)
   cout << "Could not set control handler");
   }
   Sagar
   [292]Sign In·[293]View Thread·[294]PermaLink 1.25/5 (3 votes)
   General [295]Where is the Source gone? member [296]silliconXP 18:14 31
   May '02
   This is a very good posting.it can even be better with the source
   code.kindly to send me.
   [297]Sign In·[298]View Thread·[299]PermaLink 3.11/5 (12 votes)
   Last Visit: 5:35 27 Mar '09     Last Update: 5:35 27 Mar '09

   General General    News News    Question Question    Answer Answer
   Joke Joke    Rant Rant    Admin Admin
   [300]PermaLink | [301]Privacy | [302]Terms of Use
   Last Updated: 29 May 2002
   Editor: [303]Nishant Sivakumar
   Copyright 2002 by Kumar Gaurav Khanna
   Everything else Copyright © [304]CodeProject, 1999-2009
   Web13 | [305]Advertise on the Code Project