How to shut down external application gracefully? - windows

I have a program that shuts down another application when certain conditions are met. Now most of the time everything works out fine, but sometimes the app is writing to a file and leaves it in a half finished state and has no way of recovering it on restart. I thought that one could send soft close signals and escalate after certain timeouts to more aggressive close signals, going trough a list like this:
1. WM_CLOSE
2. WM_QUIT
3. WM_DESTROY
4. TerminateProcess().
Now I know that the program has no code to handle any signal it receives. Is there a possibility that certain FileHandler under Windows react gracefully on such soft signals or is there no use to sending those, if the app does not handle them explicitly?
This article says:
NOTE: A console application's response to WM_CLOSE depends on whether or not it has installed a control handler.
Does this mean if no control handler is installed sending 1-4 is just as good as sending 4 directly?

Related

Windows service not receiving some events, particularly SERVICE_CONTROL_POWEREVENT

tldr Why don't I receive PBT_APMRESUMEAUTOMATIC, PBT_APMRESUMESUSPEND, and PBT_APMSUSPEND as the payload to service events of type SERVICE_ACCEPT_POWEREVENT?
I'm trying to detect when a windows device as woken back up from sleep. I have a constellation of processes that interact via IPC, which includes both UI applications with an event handler function provided to RegisterClassEx and services using RegisterServiceCtrlHandlerExW.
My preference is to receive these events in a service. My understanding is that I can get SERVICE_ACCEPT_POWEREVENT in dwControlsAccepted, and can then distinguish specific kinds of power event by looking at the dwEventType parameter, as per these docs https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nc-winsvc-lphandler_function_ex. However, I only ever receive PBT_APMPOWERSTATUSCHANGE, corresponding to fiddling with the power cord on the laptop. I expected to also receive some combination of PBT_APMRESUMEAUTOMATIC, PBT_APMRESUMESUSPEND, and PBT_APMSUSPEND.
When testing on the UI side, I do get WM_POWERBROADCAST events of any kind. Obviously I've missed some part of setup there. Again, the process that actually needs this info is a service, so I would have to IPC the event to a service if this is what ended up working.
For full credit, I also experimented with SERVICE_CONTROL_CONTINUE and SERVICE_CONTROL_PAUSE (enabled via SERVICE_ACCEPT_PAUSE_CONTINUE), but never receive these events at all. I had expected those to correlate with sleeping the laptop but apparently not.

Window hooks - How do they work?

I've got no idea how window hooks work at the "system level". MSDN only touches what's going on very briefly:
A hook is a point in the system message-handling mechanism where an
application can install a subroutine to monitor the message traffic in
the system and process certain types of messages before they reach the
target window procedure.
My best guess is something like below:
Before each message is added to the message queue for a window, it'll first send the message to the global/local hooks, which may do something, depending on their hook procedures. After all global hooks and local hooks, the message is finally added to the window message queue.
However, MSDN says that for some of the types of hooks, it will monitor events, notifications etc.
An example is the WH_MOUSE_LL hook:
Installs a hook procedure that monitors low-level mouse
input events. For more information, see the LowLevelMouseProc hook
procedure.
When they say events, are we talking window messages, or do they mean something else?
Am I all wrong?
Yes, this is a mechanism for windows messages, you can process this data (messages) before they reach target window procedure (message loop).
If you want hook other process windows you can simply do this in DLL, and use DLL injection for inject your library to other process.

How to avoid MQRC2033 NO_MSG_AVAILABLE

I have a simple program to process messages from a queue.
My intention is to process all available messages in queue and still listen to queue for incoming messages.
I have written the processing part inside a infinite loop as i want it to listen to queue always and process messages.
Once after processing all messages again it tries to get a message(as it is inside a infinite loop) from the queue and there
is no messages it throws MQRC 2033 NO_MSG_AVAILABLE exception(infact it is correct) and my program exits.
Can someone give an idea to continously listen to this queue and avoid this exception.
When you execute the MQGET API call, there is an option to have the program wait for messages. You can specify a wait time (in milliseconds) or specify to wait forever. Just make sure that if you have the app wait for more than a few seconds, also specify 'Fail if Quiescing'. This allows the queue manager to be stopped cleanly. Without 'Fail if Quiescing' the administrator will need to issue a preemptive shutdown which can cause problems.
There is a section specifically for this question in the Programmer's Guide in the Waiting for Messages chapter. Depending on the language you are writing in ,the actual value to specify is in the Programmer's Reference, the Using Java manual or the Using .Net manual. Each of these will be visible in the navigation panel when you click the link above.

Windows Messages in Library Code

I am porting a library to Windows. In a function I need to block on the arrival of a WM_DEVICECHANGE message.
What options are available for doing this? As my code resides in a library I have little-to-no information on the current set-up (so if it is a Console application, a regular GUI application, if my code is being run in a spawned thread, and so on). Therefore what is the best way to wait for the arrival of a specific message?
Blocking and receiving Windows messages are mutually incompatible. You get messages by pumping a message loop. Since you cannot rely on the app pumping one, you'll need to do this yourself.
You will need to create a thread. Create a hidden window in that thread then run the standard message loop. The window procedure for that window can see the WM_DEVICECHANGE message. It can do what ever it needs to do, within the constraints of running inside a separate thread. Like setting an event to signal that a function should stop blocking.
The message is probably sent using BroadcastSystemMessage(). You could create a hidden top-level window and its window proc would probably get this message. I'm not sure; but that's what I'd try first.

Why do other applications still shutdown even when I return FALSE to the WM_QUERYENDSESSION message

I have small app with a Window that is listening for the WM_QUERYENDSESSION message and returning FALSE - which should tell Windows that I don't want it to shutdown (see this MSDN link).
What I have found is that even though I am asking Windows to not shutdown, and Windows is itself not shutting down, it is still sending the WM_ENDSESSION message and closing other applications that are running alongside my own.
Does anyone know why this is happening and what can be done so that my application also prevents other applications from shutting down?
I have found that the order in which I start my application and other applications on the system affects which ones are shutdown and which are not.
A bit more research uncovered a system call to SetProcessShutdownParameters(). Using this call I can place my application at the front of the list of processes to be asked about shutting down Windows and so prevent the other applications from ever getting the WM_ENDSESSION message.
So to summarize:
When a shutdown event occurs (shutdown, restart or log off), Windows sends out a WM_QUERYENDSESSION message to each application in turn.
If an application doesn't object to the shutdown (they return TRUE), they are then sent a WM_ENDSESSION message.
As soon as one application returns FALSE to the WM_QUERYENDSESSION the shutdown is aborted, and no further messages are sent out.
Please look into this msdn article: http://msdn.microsoft.com/en-us/library/aa376890(VS.85).aspx
Basically, it really depends on what each application do with the WM_QUERYENDSESSION and the WM_ENDSESSION messages. As stated in the above article, WM_ENDSESSION messages are sent no matter what with the results of the WM_QUERYENDSESSION messages. Many applications decide to shutdown no matter the result.
There is also many application that start their shutdown process right after receiving the WM_QUERYENDSESSION to give them more time to shutdown before the dreaded "this application is not responding..." dialog
Hope this clarifies things a bit

Resources