I'm trying to develop a simple test suite for code that shuts down a Windows system. The requirement is to programatically determine if the system has actually received a shutdown call before it is powered off (to pass this result further to the test suite) and the precise shutdown INITIATION time.
So far I've tried several different approaches none of which seem satisfactory:
1) Monitoring and catching WM_QueryEndSession call
Drawbacks: basically, this call is commonly used to notify running apps and interactive users of the system shutdown. However, this call might not work with a non-responding app or service. Or the actual shutdown might be delayed till the unresponsive services are terminated and apps are closed by the system, even though the call exited with the correct status.
2) Windows Event Log It could be possible to develop a program to read Windows event log. The program would require some time to scan through the event log and verify if the the relevant message was logged or not. But it looks like that would take some time and probably wouldn't complete before the system initiates Event logging service closure and further shutdown. Moreover, running a program during system shutdown doesn't seem reliable.
3) Simply pinging the computer to make sure the network adapter was disconnected from the network. That is not the first action taken in the shutdown process and might be significantly delayed by non-responding processes and other reasons.
Is there any reliable way to catch a shutdown call to the system before the system gets powered off?
To be honest, my brain is screaming NO. The whole idea seems flawed. It sounds like a desperate attempt to address a symptom of an entirely different problem. Furthermore, testing beyond certain boundaries is generally ill-advised, and with good reason: it over-complicates things to the point where it really is not worth the effort. For example, in this situation where you're testing shutdown:
This is a situation where it is usually more appropriate to mock the interface to the problematic boundary. Then you simply test that the interactions with the mock are correct.
However that said, I still worry that you're trying to address symptoms of a different problem.
You said: "There was a discrepancy with some Windows deployments (not all, though)".
Did you identify the root cause of the discrepancy? If you have an application that's supposed to automatically issue a shutdown command, there are a number of reasons it could fail:
Getting back to "symptom of a different problem"... Some things you've said (checking event log, concerned about the time, saying: "catch if the shutdown call was issued to the system") suggest you're trying to find out after-the-fact "was the shutdown command issued"?
This doesn't sound like a testing issue - this sounds like a logging issue.
Perhaps you want to test that this very important logging is happening correctly?
And this brings me straight back to: rather mock the Windows API calls, and test that your interactions with the documented API are correct.
If I haven't dissuaded you from taunting the gods of madness...
You mentioned a drawback to monitoring WM_QueryEndSession of apps/services not responding. However, you don't really care about other apps. You only need one app, your app. A tiny simple stand-alone monitoring utility if necessary. When it gets the message - log it along with the reason. (There's still no guarantee shutdown will complete of course.)
You can go a step further, your monitoring app can use the SetProcessShutdownParameters function to be one of the first processes notified of the shutdown. Of course if shutdown is aborted, your monitoring utility will no longer be running, and will need to be restarted. (Did I mention madness and insanity?)
Alternatively, set it to be one of the last shutdown allowing you to take some action at a time closer to actual shutdown (if it does in fact shutdown).
Your concerns with reading the Event Log were because it might be too slow to finish while the system is shutting down. Why would you even want to read it during shutdown? (Or has the madness taken hold already?) The data is unlikely to run off while the disks are parking off doing nothing. Read it on restart if you have to. But first read about the Shutdown Event Tracker.
Finally, instead of (or in addition to) listening for WM_QueryEndSession, listen for WM_EndSession. There are some situations where the former won't be sent. But as far as I can tell, the latter should always be sent.
Did I mention madness? ... Maybe it was insanity. ... I know I mentioned the loony-bin. ... What who why when how? ... They're inside my head!
The madness ends.