For example we have a Win32 application which on close of main window hides to tray.
When user reboot or shutdown OS applications were closed in some way.
How to handle properly this closing event?
This is documented over on MSDN: Shutting Down.
Essentially you need a top-level window that listens for either WM_QUERYENDSESSION or WM_ENDSESSION or possibly both. You get an opportunity to perform shutdown related tasks when these messages arrive.
Applications with a window and message queue receive shutdown notifications through the WM_QUERYENDSESSION and WM_ENDSESSION messages. These applications should return TRUE to indicate that they can be terminated. Applications should not block system shutdown unless it is absolutely necessary. Applications should perform any required cleanup while processing WM_ENDSESSION. Applications that have unsaved data could save the data to a temporary location and restore it the next time the application starts. It is recommended that applications save their data and state frequently; for example, automatically save data between save operations initiated by the user to reduce the amount of data to be saved at shutdown.
If you wish to show UI during shutdown, perhaps because your app is performing critical actions that cannot survive interruption, then you can use ShutdownBlockReasonCreate.
If an application must block a potential system shutdown, it can call the ShutdownBlockReasonCreate function. The caller provides a reason string that will be displayed to the user. The reason string should be short and clear, providing the user with the information necessary to decide whether to continue shutting down the system.
Note that this process was changed dramatically from Vista. If you need to support XP then you may need code that behaves differently under XP. That topic is also covered on MSDN: Application Shutdown Changes in Windows Vista.
You should handle the System Shutdown Messages WM_QUERYENDSESSION and WM_ENDSESSION.
Shuting down should cause a SIGTERM or SIGINT be sent to you program.
You can handle this via .
Ref: http://www.cplusplus.com/reference/csignal/signal/
void my_handler (int param)
{
// clean up here
}
int main ()
{
signal(SIGINT my_handler); // try also SIGTERM
}
Related
Basically what the title says I need to detect when my program is ending like when someones clicks on end task in the task manager or something. Can anyone point me to some kind of event that handles this with an example or something? Thanks for any help given
You need to open this process. This way you will retrieve its handle. After that you can simply wait on this handle.
HANDLE h = OpenProcess(....);
WaitForSingleObject(h);
Handles of the processes and threads in many ways look like Windows event handles. Once this process or thread finishes, they get signaled.
It depends on how your app is terminated and what type of app it is.
For apps with an UI:
If the user clicks "End Task" in the task manager, you will actually receive WM_DESTROY and even WM_CLOSE messages to your message handler.
If the user simply clicks the X button of your app, obviously the above also applies.
If the user logs off or shuts down the PC, you'll receive WM_QUERYENDSESSION and WM_ENDSESSION messages.
For console apps, you can use the SetConsoleCtrlHandler function to be notified of most cases of app termination (I don't have any experience with this so can't give many details).
For services, you can use the RegisterServiceCtrlHandler function in much the same way.
For all types of apps, if the app is terminated forcibly by another process via the TerminateProcess function, there is no way to get notified:
If a process is terminated by TerminateProcess, all threads of the process are terminated immediately with no chance to run additional code. This means that the thread does not execute code in termination handler blocks. In addition, no attached DLLs are notified that the process is detaching.
My application throws some strange errors if you shut down the computer while my application is running.
Sometimes the message is (address) memory can not be "read", sometimes can not be "write".
Shutting down the application in the normal way doesn't generate such messages.
How can I simulate the "windows shutdown" so that I can debug my application? How can I find out what the application is trying to do that it cannot?
When Windows wants to shutdown, it sends a series of events to the application; such as WM_ENDSESSION and WM_QUIT. You can process these in the message handler you are using; in general the application will need to respond appropriately and quickly to these messages else the OS will just terminate the application anyway. I'm not sure what default processing wxwidgets offers in this regard. Hooking into these would help in diagnosing the application error itself.
There are a few things you could attempt to do;
The shutdown sequence will not be easy to simulate (if at all) - a lot happens during shutdown; the exact state and situation is difficult to simulate in it's entirety.
In terms of diagnosing the state of the application just before shutdown, you could try to process the WM_QUERYENDSESSION and respond with a FALSE to prevent it from shutting down (with newer versions of Windows you can no longer prevent the shutdown, so it may not work depending on the platform you are on).
You could also try to test the application's immediate response to WM_ENDSESSION message by sending it the WM_ENDSESSION (e.g. via a PostMessage) with the appropriate data as detailed on MSDN.
For terminal based applications;
You can also hook in the signals (SIGKILL I believe) if required. See this Microsoft reference for more detail. You can also the the SetConsoleCtrlHandler hook. But since you using a toolkit, it would be better to use the messages sent to the application already.
if a user decides to force close my application(like through the task manager) is there a way i can quickly execute some clean up code before the application closes? i'm coding in c++ btw
It depends on how the process is instructed to close. It is possible to do this upon graceful exit, but not for anything forcefully closed.
If the process is closed via TerminateProcess or ExitProcess, you won't be able to perform any graceful cleanup. TerminateProcess is how Task Manager and utilities like Sysinternals pskill end a target process. ExitProcess is called within a process but is not typically used to exit.
If the process has a message pump on one thread (typically the first thread in the process) and no other threads running that are running code whose lifetimes are independent of activity in that thread, then a WM_QUIT message will signal that the process should close (semantically, that the app should close, your process might conceivably stick around for a while for other reasons), and you can run cleanup code upon receiving the message. Depending on your needs, in a windowed app you might consider performing cleanup operations as early as WM_CLOSE or WM_DESTROY.
If you have written code in a DLL, there are notifications that you can handle in DllMain that will allow you to perform last-chance cleanup (DLL_PROCESS_DETACH), which can potentially cover the case of a process exiting without having a message pump. However, this is not a great way to perform cleanup for code that strictly relies on any C/C++ runtime (or any other DLL), as the runtime might be unloaded first.
Last, for any graceful close where you control what runs in WinMain or main, you can always do whatever cleanup you need to do before either function returns, sending control back to the windows subsystem. This is preferred and usually safest for most application needs.
If you are using a message pump, handle the WM_QUIT message.
Also: What is the difference between WM_QUIT, WM_CLOSE, and WM_DESTROY in a windows program?
EDIT
Im sorry, I read over the fact that you want to handle termination, eg by the task manager.
This might help you though: How to catch event when Task manager kill your C++ application
I'm studying some codes about RS232 with Borland C++. The implementation of reading data from the port is polling the status of the port by timer. There are some events checking whether the status of the port changed. If the status changed, events trigger the data-reading subroutine.
However, I think that polling is so bad that much resource is spent on the action. Could the program be passive in monitoring the port without any aggressive polling or something else? In other words,
the program hibernates unless some events which triggered by incoming
data in the port activate it.
Is the idea is possible?
Thank you for reading
Best regards
I think for your requirements the design pattern named Reactor is appropriate. Reactor is based on the system call 'select' (which is available in both Unix and Windows environments). From the referenced document,
Blocks awaiting events to occur on a set of Handles. It returns when it is possible to
initiate an operation on a Handle without blocking. A common demultiplexer for I/O
events is select [1], which is an event demultiplexing system call provided by the UNIX
and Win32 OS platforms. The select call indicates which Handles can have operations
invoked on them synchronously without blocking the application process.
You can see that this pattern is encoded as a library in several frameworks such as ACE, Boost.
If you are working with the Win32 API functions for reading the serial port you can call ReadFile. It will suspend until it has the number of bytes you requested or until a timeout that you can set. If your program is a GUI then the serial read should be in a secondary thread so the GUI thread can react to any received Windows messages.
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 :)