How DO you destroy objects on console close?

Dec 10, 2011 at 3:13am
I'm writing a server in a console, and I need to deallocate some memory when the user simply clicks the X button on the console window. atexit() doesn't work nor does a global object destructor, etc...

Is there even a way?
Dec 10, 2011 at 4:26am
You need to use SetConsoleCtrlHandler().
http://www.google.com/search?btnI=1&q=msdn+SetConsoleCtrlHandler

Here's an example I whipped up for you.
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
#include <iostream>
#include <limits>

#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

BOOL WINAPI ConsoleCtrlEventHandler( DWORD dwCtrlType )
  {
  switch (dwCtrlType)
    {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
      // Do nothing.
      // To prevent other potential handlers from
      // doing anything, return TRUE instead.
      return FALSE;

    case CTRL_CLOSE_EVENT:
      // Do your final processing here!
      MessageBox( NULL, "You clicked the 'X' in the console window! Ack!", "I'm melting!", MB_OK | MB_ICONINFORMATION );
      return FALSE;

    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:
      // Please be careful to read the implications of using
      // each one of these, and the applicability to your
      // code. Unless you are writing a Windows Service,
      // chances are you only need to pay attention to the
      // CTRL_CLOSE_EVENT type.
      return FALSE;
    }

  // If it gets this far (it shouldn't), do nothing.
  return FALSE;
  }

int main()
  {
  using namespace std;

  if (!SetConsoleCtrlHandler( &ConsoleCtrlEventHandler, TRUE ))
    {
    cerr << "Fooey!\n";
    return 1;
    }

  cout << "Close the console window to see some action!\n";
  cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

  return 0;
  }

Remember, if you are writing a Windows Service, there is a better way to do this. (I'm pretty sure you can find it through the link I gave you. Ah, here it is: http://www.google.com/search?btnI=1&q=msdn+Handler+Callback+Function )

Keep in mind that this method has issues on some older systems. (I don't remember which ones right now.)

Also, if you do return TRUE for any of the options, the user will be presented with an obnoxious and cryptic Microsoft message asking if the user really wants to terminate the application now or cancel.

Hope this helps. :O)
Dec 10, 2011 at 7:46am
1
2
3
4
			  CWindow myWindow;
			  //this is the parent window and can be replace by the command window pointer 
			myWindow.Attach(this->GetSafeHandle());
				myWindow.DestroyWindow();
Dec 10, 2011 at 11:12pm
Thanks, Duoas! I have the same code for any of the cases, as it said it will have already closed the app before the services are notified, and the Ctrl+C and Ctrl+Break have the same memory leak problem as closing the application.

It works perfectly, thank you. Though, would I need to worry about calling the destructors of other global objects like std::cin, std::cout, std::clog, std::cerr, etc... ? I don't want my application to be too leaky.

@bluecoder: what would that be for? I'm writing a console based server, it doesn't need any more GUI than the console provides ;)
Dec 11, 2011 at 3:48am
bluecoder's solution is if you are writing a Windows Service using MFC (I think). (You don't need it.)

You don't ever need to worry about destructing standard objects.
You do need to worry about properly destroying your own resources. Make sure to structure your application so that it works properly.

(I think you could just call exit( 0 ); in your handler to have stuff like that handled, but I haven't taken the time to be too careful about what exactly that entails -- and how well it would work.)
Topic archived. No new replies allowed.