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...
#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()
{
usingnamespace 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;
}
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.
CWindow myWindow;
//this is the parent window and can be replace by the command window pointer
myWindow.Attach(this->GetSafeHandle());
myWindow.DestroyWindow();
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 ;)
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.)