I am making an RPG game with C++/x86 asm. My question is related to the C++ component. In C++/win32 how would I detect if the computer is shutting down or turning off, or whatever else - so that I can save the game session. My game has a 'save' option, but if the user or another program decides to shut off the computer how can I detect this with some kind of API hook so that I can instantly save the game session to the text file.
Now please don't suggest an option by creating a thread to run passively as I want to keep the file size to a minimum, so if you can suggest some sort of WM_ hook that would be great. I'd refer to MSDN but I don't want to be searching for hours through their WM directory.
You can handle session saving in response to the WM_ENDSESSION message. Note that after your message handler returns from handling this, your process may be terminated at any time, so you need to save it directly during the message handler, and not just set a flag to let some later code handle the saving, because that later code might not get to execute.
A comment suggests the WM_QUERYENDSESSION message. This has a slightly different meaning: it gives applications the chance to complain about the session ending, and gives the user a chance to not log off / shut down the system. Based on your question, you have no intention of preventing any such thing, so WM_ENDSESSION seems like a better match to me.
Related
I need to adjust something by a regular desktop program (not a service) when the system emerges from a sleep state. I expected that the program would get a WM_POWERBROADCAST message, but this message is never received.
According to How can I know when Windows is going into/out of sleep or Hibernate mode?, this message is expected without any preconditions.
Tested on Windows 11 with a simple Win32 program, generated by Visual Studio. Just added to the message loop "case WM_POWERBROADCAST:", which sets some static variable. After waking up from sleep, the variable is untouched.
You can verify with Spy++: there are only multiple WM_DEVICECHANGE messages, plus 0x02C8 and 0x02C9 messages, and repainting messages.
The workaround is to constantly poll the system with, for example, GetTickCount64(), and detect periods of inaction. Of course, better to avoid polling.
If you know something about it, please let me know what I am missing!
You have to register before you will get WM_POWERBROADCAST messages.
Take a look at Registering for Power Events, you will see that you need to call RegisterPowerSettingNotification() in order to get WM_POWERBROADCAST.
I'm working on a embedded solution where two apps are working: one is the user interface and the other runs in the background providing data for the UI.
Recently I came across with a memory leak or similar error that is making Linux kill the secondary process, leaving the UI in a stopped situation without telling anything for the user about what is going on. I reached the problem by reading Linux's message log file and the software's print on terminal "Kill -myapp".
My question is: how could I notice such an event (and other similar) coming from the secondary software so I could properly report it to the user and log it? I mean, it's easy to have a look time to time in the process 'tree' to see if the secondary app is running and, if it's not, report a "some event happened" in the UI and it's also plausible to have a error-handler system inside the secondary app that makes it write in a log file what just happened and make the UI read that file for new entries from time to time, but how could the UI app knows with better details what is going on in such more abrupt events? (in this case, "Linux killed process", but it could be a "segmentation pipe" or any other) (and if there is another, better solution that this "constant read a log file produced by the secondary app", I'ld also like to know)
Notes: the UI is written in C++/Qt and the secondary app is in C. Although a solution using the Qt library would be welcomed, I think it would be better for the entire programming community if a more generalized solution was given.
You can create a signal handler for POSIX signals such as SIGKILL in the backend process and notify the ui using for example another signal with sigqueue. Any IPC mechanism should work, as long as it's async safe. Read more about signals: tutorial and manual
It may still be a good idea to check from the ui side periodically because the handler might not succeed.
As for a better way to check if process is alive compared to reading the log file:
Check if process exists given its pid
I am using visual studio 2010 to develop a windows form application using c++.
This program waits for an event like connection request and displays a message
But this program is shown as "not responding" in windows task manager.
Is there any way to make the program appear responsive ??
The standard practice for this situation is to use multi-threading. Create a background thread to wait for the connection request or whatever event you need that might cause the primary thread to block.
This allows the user interface of your application to remain responsive. If you don't use a thread, the primary UI thread will be blocked waiting for the request and can't handle other events such as drawing the form, responding to window events, etc.
In Windows programming, any activity that is going to take a significant amount of time should be threaded. This isn't a hard rule, but a pragmatic amount of threading will make a world of different in giving your application a smooth, responsive feel. The primary thread should be reserved for drawing and handling user interaction.
A Google search will give you plenty of examples, but here is a decent one to get you started.
Say, if I open a Notepad, type something in it and don't save it, then call the following API from the same user session:
ExitWindowsEx(EWX_LOGOFF, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED);
That user session will enter a "shut-down state", where OS will show an overlay window displaying a message that Notepad prevents system from logging off a user. This overlay will not go away until a user clicks "Cancel" or "Force Quit" buttons.
So two part question:
Is there any way to know which processes blocked logging-off/shut-down process?
Is there any way to cancel this user-session "shut-down state" programmatically?
PS. This state can be detected by calling GetSystemMetrics(SM_SHUTTINGDOWN);
EDIT: Contrary to the answer below, I am not trying to stop system from shutting down, nor that any user-mode process is "hung."
EDIT2: Here's a screenshot of the overlay I'm trying to cancel/close:
Question 2: "Is there any way to cancel this shut-down state programmatically?"
The short is answer is not really. And neither should you want to really stop shutdown programatically UNLESS: shutting down will result in serious data loss or significantly affect the user experience on a subsequent system start up. But to mention just one example: imagine a computer is overheating - stopping shutdown programmatically could result in a fried system (and a very irate user).
System shutdown is also not the only thing you need to monitor. There's also hibernate and suspend events (have a look at WM_POWERBROADCAST message).
That said, Windows provides a plethora of mechanisms for detecting system shutdown. For instance:
If your application has a message pump you can choose to return FALSE when Windows polls running applications to vote on WM_QUERYENDSESSION , however Windows from Vista onwards will still force a shutdown after a time-out. From Vista onwards you can (and need to) ShutdownBlockReasonCreate after returning false to WM_QUERYENDSESSION.
If your application is running as a service you can use RegisterServiceCtrHandlerEx and then SetServiceStatus to get a 3 minute shutdown extension grace by setting SERVICE_ACCEPT_PRESHUTDOWN which will get you a SERVICE_CONTROL_PRESHUTDOWN notification. Naturally, you won't receive logoff notification because a service is not affected by logoff. Pre-Vista you can register for SERVICE_CONTROL_SHUTDOWN notification.
Console applications (and gui apps as well but it does not make sense) can use SetConsoleCtrlHandler to be notified of CTRL_LOGOFF and CTRL_SHUTDOWN_EVENT.
At a much lower level one can try hooking API functions such as NTShutdown or even NtSetSystemPowerState which apparently is "the last thing called during ANY type of reboot". But I would strongly suggest not to attempt this.
That said there are ways to really strongly insist that the system should not be shutdown.
Consider the following:
1.) Try to register your application to be first in line to receive Shutdown notification. Something like:
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686227(v=vs.85).aspx
if(!SetProcessShutdownParameters(0x4ff, 0)) // greedy highest documented System reserved FirstShutdown
{
// Fallback
if(!SetProcessShutdownParameters(0x3ff, 0)) // highest notification range for applications
{
// shouldn't happen
}
}
2.) Return FALSE on WM_QUERYENDSESSION
From Vista onwards call ShutdownBlockReasonCreate() after returning false on WM_QUERYENDSESSION.
3.) Tell Windows that you need the system to stay up and available. Have a look at
http://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
4.) Clean up, call ShutdownBlockReasonDestroy() on Vista onwards, and THEN shutdown the system cleanly.
You could also try the undocumented function (at least it's not on MSDN anymore) CancelShutdown in "user32.dll" which at some point (still may) used to function very much like calling shutdown.exe with the abort flag.
Your mileage may vary.
Following your edit which makes your question clearer:
If you monitor WM_QUERYENDSESSION and respond FALSE to it you can poll from your still running process for a predetermined period of time and then issue an ExitWindowsEx call with flag EWX_FORCEIFHUNG, for example on WM_ENDSESSION. Or you could actually call this pre-emptively on receiving WM_QUERYENDSESSION - the problem is: what if forcing the shutdown results in serious data loss? You're not doing the user of the system any good at that point.
Update following your comments:
How about this:
To find out blocking application:
Register your app with SetProcessShutdownParameters to be first in
line to get WM_QUERYENDSESSION.
Respond FALSE to WM_QUERYENDSESSION and on Vista onwards call
ShutdownBlockReasonCreate to buy yourself the time.
Get the first window in the chain HWND top = GetTopWindow(NULL)
Get the process ThreadId from hwnd GetWindowThreadProcessId() (compare it with your running app's ;) )
Use SendMessageTimeOut with a message to the hWnd - if you receive
no response (timeout) you may have found the blocking window. Go to step 6.
If not skip to 7.
Use OpenProcess() with the handle returned from
GetWindowThreadProcessId to get a process handle and call
GetModuleBaseName() to get the name of the hung process.
If you haven't found the hung window, enumerate the next Window with
GetNextWindow() and go back to step 4.
You can also try using the enumerate window handle technique above to find out if you can get a handle to the "hung window" overlay. Having this might give you a chance to do a send key to cancel the state. My bet is that you won't be able to access it but I haven't tried :)
Again your mileage may vary :)
I am developing a simple WinAPI application and started from writing my own assertion system.
I have a macro defined like ASSERT(X) which would make pretty the same thing as assert(X) does, but with more information, more options and etc.
At some moment (when that assertion system was already running and working) I realized there is a problem.
Suppose I wrote a code that does some action using a timer and (just a simple example) this action is done while handling WM_TIMER message. And now, the situation changes the way that this code starts throwing an assert. This assert message would be shown every TIMER_RESOLUTION milliseconds and would simply flood the screen.
Options for solving this situation could be:
1) Totally pause application running (probably also, suspend all threads) when the assertion messagebox is shown and continue running after it is closed
2) Make a static counter for the shown asserts and don't show asserts when one of them is already showing (but this doesn't pause application)
3) Group similiar asserts and show only one for each assert type (but this also doesn't pause application)
4) Modify the application code (for example, Get / Translate / Dispatch message loop) so that it suspends itself when there are any asserts. This is good, but not universal and looks like a hack.
To my mind, option number 1 is the best. But I don't know any way how this can be achieved. What I'm seeking for is a way to pause the runtime (something similiar to Pause button in the debugger). Does somebody know how to achieve this?
Also, if somebody knows an efficient way to handle this problem - I would appreciate your help. Thank you.
It is important to understand how Windows UI programs work, to answer this question.
At the core of the Windows UI programming model is of course "the message" queue". Messages arrive in message queues and are retrieved using message pumps. A message pump is not special. It's merely a loop that retrieves one message at a time, blocking the thread if none are available.
Now why are you getting all these dialogs? Dialog boxes, including MessageBox also have a message pump. As such, they will retrieve messages from the message queue (It doesn't matter much who is pumping messages, in the Windows model). This allows paints, mouse movement and keyboard input to work. It will also trigger additional timers and therefore dialog boxes.
So, the canonical Windows approach is to handle each message whenever it arrives. They are a fact of life and you deal with them.
In your situation, I would consider a slight variation. You really want to save the state of your stack at the point where the assert happened. That's a particularity of asserts that deserves to be respected. Therefore, spin off a thread for your dialog, and create it without a parent HWND. This gives the dialog an isolated message queue, independent of the original window. Since there's also a new thread for it, you can suspend the original thread, the one where WM_TIMER arrives.
Don't show a prompt - either log to a file/debug output, or just forcibly break the debugger (usually platform specific, eg. Microsoft's __debugbreak()). You have to do something more passive than show a dialog if there are threads involved which could fire lots of failures.
Create a worker thread for your debugging code. When an assert happens, send a message to the worker thread. The worker thread would call SuspendThread on each thread in the process (except itself) to stop it, and then display a message box.
To get the threads in a process - create a dll and monitor the DllMain for Thread Attach (and Detach) - each call will be done in the context of a thread being created (or destroyed) so you can get the current thread id and create a handle to use with SuspendThread.
Or, the toolhelp debug api will help you find out the threads to pause.
The reason I prefer this approach is, I don't like asserts that cause side effects. Too often Ive had asserts fire from asynchronous socket processing - or window message - processing code - then the assert Message box is created on that thread which either causes the state of the thread to be corrupted by a totally unexpected re-entrancy point - MessageBox also discards any messages sent to the thread, so it messes up any worker threads using thread message queues to queue jobs.
My own ASSERT implementation calls DebugBreak() or as alternative INT 3 (__asm int 3 in MS VC++). An ASSERT should break on the debugger.
Use the MessageBox function. This will block until the user clicks "ok". After this is done, you could choose to discard extra assertion failure messages or still display them as your choice.