0
votes

What is the proper way to 'quit' an application after final clean-up tasks have been done, in response to the WM_ENDSESSION message?

Once my application, a service-like executable responding to external input, receives this message and wParam == TRUE it writes the end of the log and flushes it. After this point, I actually want my application to stop, completely. I don't want any further code to run, because clean-up will be done by Windows and any servicing done by my application after this message is likely to be rudely interrupted by process termination.

I want my application to do only the absolutely necessary amount of work and after that stop so as to not slow down Windows shutdown. Some possibilities I can think of are:

  • One option I can think of is to call ExitProcess. However, this seems to do a lot of work and maybe too much?
  • Another option is to set a flag after receiving WM_ENDSESSION and have strategically placed checks for this flag in my code so that the program does nothing. The obvious disadvantage is that this complicates the code unnecessarily.

There might be other options and I want to know: which is the proper way?


Interesting reads

The following are some interesting reads on the subject, but none of these answers this question.

2
You've been ignoring the WM_QUERYENDSESSION notification when it gets that far. Best thing to do then is to hang your program, Sleep(INFINITE). That will annoy the bejesus out of your user, he'll be sure to file a bug report. If you don't like getting bug reports then use _exit(1);Hans Passant
@HansPassant: Except, you cannot perform your shutdown in a WM_QUERYENDSESSION handler, since there is no guarantee that a WM_ENDSESSION will follow. You can, however, flush any buffers, that need to be written out to disk, to reduce the processing time in your WM_ENDSESSION handler to its minimum.IInspectable
No, that's been over and done with for the past 10 years. Good riddance.Hans Passant
@IInspectable: If you return TRUE from WM_QUERYENDSESSION, you are guaranteed to receive WM_ENDSESSION. What is NOT guaranteed is that the session will actually end if you receive WM_ENDSESSION. This is stated in the documentation: "When an application returns TRUE for this message, it receives the WM_ENDSESSION message, regardless of how the other applications respond to the WM_QUERYENDSESSION message. Each application should return TRUE or FALSE immediately upon receiving this message, and defer any cleanup operations until it receives the WM_ENDSESSION message."Remy Lebeau
Furthermore, from MSDN's doc's on WES: "When an application returns TRUE for this message, it receives the WM_ENDSESSION message, regardless of how the other applications respond to the WM_QUERYENDSESSION message. Each application should return TRUE or FALSE immediately upon receiving this message, and defer any cleanup operations until it receives the WM_ENDSESSION message.". This seems to be opposite to what you are saying. Also the Guidelines for Applications on the subject seems to tell us to wait.MicroVirus

2 Answers

2
votes

Update:

_exit() will quickly terminate the process without the unnecessary work. (Don't confuse this with exit().)

Interestingly, the implementation of _exit() ends with a call to ExitProcess, so the DLL_PROCESS_DETACH notifications are still sent, but the runtime DLL won't run static destructors in this case because _exit() sets a flag first.

Original Answer:

ExitProcess is appropriate. It may sound like a lot of work, but much of that is going to happen anyway, even if your process crashes.

The only significant, unnecessary work might be the DLL_PROCESS_DETACH notifications to the DLLs. The best thing you can do about that is to make sure your DLLs don't do much work when they receive those notifications.

Another option would be to call abort or _exit, but I suspect these are roughly equivalent to ExitProcess.

1
votes

I agree with Adrian that ExitProcess() is usually the most appropriate choice.

However, if you absolutely must (for example) prevent the C++ destructors from running, you can always resort to the nuclear option:

TerminateProcess(GetCurrentProcess());