What is the proper way for an MFC application to cleanly close itself?
AfxGetMainWnd()->PostMessage(WM_CLOSE);
Programatically Terminate an MFC Application
void ExitMFCApp()
{
// same as double-clicking on main window close box
ASSERT(AfxGetMainWnd() != NULL);
AfxGetMainWnd()->SendMessage(WM_CLOSE);
}
http://support.microsoft.com/kb/117320
In support of #Mike's answer, the reason to use this method is to trigger the correct shutdown sequence. Especially important for MDI/SDI applications because it gives a chance for documents to prompt for save before exit or to cancel the exit.
#Matt Noguchi, your method will circumvent this sequence (which may be the desired effect, I suppose, but you've probably got problems if you're short-circuiting the normal teardown.
PostQuitMessage( [exit code] );
If it is a dialog based application you can do it by calling EndDialog() function.
If it is an SDI/MDI based application you can call DestroyWindow. But before which you will need to do the cleanup yourself (closing documents, deallocating memory and resources, destroying any additional windows created etc).
Related
We have an old MFC-based C++ gui app (Visual Studio 6.0) which often does not terminate correctly. So I would like to be able to use a instruction like "abort();" to immediately end it.
However, the abort() instruction causes a dialog box to pop up, rather than ending immediately. Using "exit(int)" doesn't work.
Is there a way to eliminate the abort dialog, or is there a better termination method?
One obvious way to abort without anything else happening ahead of time would be for it to call the Windows ExitProcess function:
ExitProcess(exitCode);
If you want to kill it from some external program, you'd do that with TerminateProcess. To do that, you'll need a handle to the process, which typically means getting its process ID. If you're doing this from a program that spawned the one you want to kill, you'll probably get a handle to it when you create it. Otherwise, you'll probably need to use something like FindWindow to find its window, then GetWindowThreadProcessId to find the ID of that window's process. Once you have that, you call OpenProcess to get a handle, and finally TerminateProcess to actually kill it.
If it is a dialog box based app, then you can use EndDialog(IDOK) method.
Let me explain my question with an example. In my app, I need to provide a way to automatically close it from within "itself." (An example of such function is when an installer/updater of my app needs it to close before installing an update. Another example is when my app performs actions on schedule and needs to automatically close once it's done.)
I picture that in the simplest situation posting the WM_CLOSE message to the own window will accomplish this task, but there're the following cases that will not work with just that:
My app may be displaying an arbitrary number of child dialog windows.
My app may be displaying a common control window, such as Open File dialog:
or this one, but there could be others:
And lastly what could one do if the close button is not even available:
At the current point, I simply resort to terminating my process (either with the exit() method from within, or with TerminateProcess from outside.)
But I'm curious, if there's a more graceful way of closing my GUI app (from within)?
There is no single answer, it depends on your app's architecture and what it's doing. I don't quite understand why you would want to force close your application while it is in a common dialog, but if you do, then exit() is safe. In that case the process is actually shutdown from the operating system's perspective as opposed to a forced termination (TerminateProcess). In theory TerminateProcess might leave objects in the OS (DLL global data and such) in an inconsistent state, and exit() will be cleaner in that regard.
Generally though I'd avoid having visible UI that is up for the user just disappear and instead close the windows in reaction to some user choice.
But, exit() will work.
You can use exit() but a safer way to close the window would be:
SomewWindow->ShowWindow(SW_HIDE);
You could then destroy the window object or show the window later.
I have a C++ Win32 application written using Win32 API and I wish to force it to exit in one of functions. Is there something like Exit() or Destroy() or Abort() something similar that would just terminate it?
Aiiieeeeeeeeeeee. Don't do ANY of these things!
exit() and ExitProcess are the equivalent of taking a gun and shooting the process in the face. I hope I don't have to explain why that isn't nice, especially for processes that are holding shared objects like database handles that might be system-wide. I know that's the norm in Android, but this is Windows and we don't do that 'round here.
Calling PostQuitMessage() directly can cause memory leaks. PostQuitMessage() is intended to be called from WM_DESTROY. It is NOT NOT NOT a message intended to be used to ask a window to close. It's a callback mechanism for applications to post their exit code back to the shell. It is intended to populate WM_QUIT with the application exit code. If you call PostQuitMessage() directly, you will bypass WM_DESTROY entirely. This is problematic because many windows--and child widgets--very correctly perform their clean-up in WM_DESTROY. If you skip this message by lying to the window, you will deny components the chance to clean up.
And since we're on the topic, don't call WM_DESTROY directly either. Raymond Chen of Microsoft has a wonderful article where he explains "Sending a window a WM_DESTROY message is like prank calling somebody pretending to be the police". It's sort of the evil-twin of PostQuitMessage. Instead of exiting without cleaning up, you're asking the window to clean up without exiting. The window manager never knows to remove the components, and you're left with a dead orphan window in memory. Sigh.
The correct answer is to post WM_CLOSE. Anything using the default window procedure will correctly notify the window manager to destroy the window which will cascade on to WM_DESTROY then to WM_QUIT as intended.
If you need different behavior than the standard close, the other alternative is to create a WM_USER or WM_APP message. If your window has a "fancy" WM_CLOSE--say, for example, you give the user a prompt "Are you sure you want to exit?"--and you want to skip that, you may define a custom message with WM_USER or WM_APP and call that in its place. Your app-defined message would implement the default close behavior, and the WM_CLOSE that's tied to the system gadgets performs your fancy behavior.
I hope that helps!
PostQuitMessage() is the standard, graceful way of quitting a windowed application.
It will not immediately quit but rather post a quit message that will get parsed by your main loop (if done correctly) and then quit the application.
If you're using a Win32 application with a proper window procedure, you can use the function PostQuitMessage.
If you're working with visual C++, then use:
PostQuitMessage()
ExitProcess is the function to use, else you can use exit, note that neither insure the integrity of the shutdown (ie: you many leak handles etc and threaded operations will be terminated, even if they are halfway through an operation, like a db commit)
Yes, it's exit()
http://www.cplusplus.com/reference/clibrary/cstdlib/exit/
Just return from the WinMain function. If you have a message loop, use PostQuitMessage to break out. Don't try to exit the process in the middle of execution; it's sloppy.
I have a third party encryption library, which may create a MessageBox if key creation fails. The failure can be caused by bad random number generation or other rarities, and in most cases, trying again will result in success. My code will attempt key creation up to three times before deciding it failed.
Now, the issue is that the program may be used with automation. If a MessageBox is created during automation, it will block the process forever, because there's nobody to click the 'OK' button.
Does anyone know of a way to catch when this message box is created and automatically close it?
Anything is fair game, as long as it's not something that will make security suites angry. This means no hooking or code tunneling.
In summary, I need to catch when a MessageBox is created and close it. The MessageBox's creation is outside of my control. Modifying the code at runtime is not acceptable.
Also, I've noticed there are some other similar questions, but they don't have the same requirements.
EDIT: Additional note, I can find the message box via searching through all windows until I find one with a matching title and then send it a WM_CLOSE message, but I don't think this is a great solution. I also have no guarantee that the message box has been/will be displayed, or how long after my call it will be displayed. It could display instantly, it could display 1200 ms later, or it could not display at all.
Just before you begin the encryption process, install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, or if that doesn't work post a WM_CLOSE (or a BM_CLICK to a relevant button if selecting an option is necessary). Uninstall the hook after the process for not messing with every possible dialog your application pops up.
That sounds like bad design on the part of that library. Generally any sort of utility library (like encryption) has no business invoking any kind of GUI (unless you explicitly ask it to).
Is there possibly some configuration or setting in this library that could disable its use of message boxes?
If not, I'd suggest that you might want to investigate using a different library. After all, if the designers of this library have already made this kind of poor design decision once, then there may be other unfortunate surprises lurking in there.
You can hope that it will be found by GetForegroundWindow, but this may catch other applications. The more brute force way is to iterate over all windows with EnumWindows looking for something that has a caption or text equal to this shown by the library.
I have once "remote controlled" an application by sending mouse click events to some controls. I guess you would have to do this in a separate thread that is watching for Events if a window is opened. Pretty ugly but working...
Create a new thread. If your function fails and a Message Box is opened, obtain a handle to the message box by looping through the windows (GetTopWindow, GetNextWindow) and comparing the window's process id to the one returned from GetCurrentProcessId().
Or, you can avoid all the hard work and just hook the MessageBox API with detours. It's not very hard, and if you don't want to pay for detours, you can do it manually.
Call VirtualProtect and set the memory protection at MessageBox at PAGE_EXECUTE_READWRITE
Create a naked function, and use it as a trampoline.
Create a function identical in parameters to MessageBox (this will be your hook)
Create a jump from MessageBox to your hook function.
Is there a way to guarantee that your system tray icon is removed?
To add the system tray icon you do:
Shell_NotifyIcon(NIM_ADD, &m_tnd);
To remove the system tray icon you do:
Shell_NotifyIcon(NIM_DELETE, &m_tnd);
What I want to know: what if you application crashes? The icon stays in your system tray until you mouse over. Is there a way to guarantee that the icon will be removed, even when the application crashes? I would prefer not to use structured exception handling for various reasons.
Another case that I want to handle is when the process is killed, but doesn't necessarily crash.
Another thing most programmers forget to check for is if the explorer restarts/crashes. Its nice if the application handle this and recreate its own icon.
Just check for Message WM_TASKBARCREATED and recreate the icon.
You could have a separate, simpler (and thus presumably more robust) program which monitors your application. This program could actually launch your program and then monitor the process. Yeah, this is a very ugly solution.
Personally I would use a Vectored Exception Handler. Yes, it's based on SEH, but you don't have to deal with all the different stack that you might need to unwind.
TerminateProcess() is must more destructive. You really can't guard yourself against that; when it happens your process is dead. No ore instructions are processed, so it does not matter what code there is in your application.
An external application wouldn't really help, would it? It too could crash, or be killed.
Hmm, you can always have an external monitor process call SendMessage with the WM_PAINT message to the system tray window (which you would have to do based on the class of the window). That should remove the icon which is no longer valid.
There are many ways to ensure the call to Shell_NotifyIcon(NIM_DELETE, &m_tnd); in C++ for the case of the application crhashing; using a RAII wrapper over the NOTIFYICONDATA you're using will do the work, for example:
struct NID
{
NID() : icon_data() { icon_data.cbSize = sizeof(icon_data); }
~NID() { Shell_NotifyIcon(NIM_DELETE, &icon_data); }
void Show(HWND w) { icon_data.hWnd = w; Shell_NotifyIcon(NIM_ADD, &icon_data); }
NOTIFYICONDATA icon_data;
};
This is a simplified version of the wrapper but it will illustrate the main idea: if you create an instance of NID in static storage it will be initialized before the WinMain or main call and its destructor will be called on the program cleanup, even if this cleanup is due an abnormal termination.
So, we can use this NOTIFYICONDATA resource wrapped in struct NID this way:
NID nid; // <--- automatic storage duration, cleared after WinMain return
// even if it returns normal or abnormally
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
// GetMessage(&message, NULL, 0, 0) loop ...
// ...
// use nid.icon_data as you please
}
catch (...)
{
// something bad happened...
}
return 0;
}
The example above calls the ~NID() when the program terminates (after an exception or after closing the program), the destructor will call Shell_NotifyIcon(NIM_DELETE, &icon_data); and the icon is deleted from the notification area; this code covers the normal termination and the exception termination, you can read more about this topic in this good answer from NPE:
As for the kill the process case there's no simple way to do this.
I've already tested that std::atexit and std::at_quick_exit functions aren't called after killing the program through the task manager so I guess that you must hook the termination call... it seems a pretty complex task but is explained in this answer from BSH:
When a process is terminated (not closed) nothing realy can be done unless you start do some hooking, either by hooking TerminateProcess or NtTerminateProcess in the Task Manger process
Hope it helps (though is an answer 6 years later lol)
You have to handle the applications exit when crashing some way or another or the icon will not disapear.
Check this out if it can be any help: http://www.codeproject.com/KB/shell/ashsystray.aspx
You can use SetUnhandledExceptionFilter to catch the crash. I normally use it to create a crash dump file so that the crash can be debugged, but there's no reason you can't so some simple cleanup like removing tray icons.
Does not directly address your problem, but this was a very helpful work around for me:
I wanted to avoid confusing system-tray states. So for me, it was sufficient to 'refresh' the notification tray on startup. This was trickier than I first thought, but the following demonstrates a SendMessage solution that simulates a user-mouse-over cleanup that doesn't involve needing to actually move the user's cursor around.
Note that on Windows 7 machines the name Notification Area should be replaced with User Promoted Notification Area.