My app needs to block sleep/hibernate mode. I have the code in place, but after successfully catching the WM_POWERBROADCAST message, neither PBT_APMQUERYSUSPEND nor PBT_APMQUERYSTANDBY are being caught successfully. Interestingly, the PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC messages are being caught by my app.
Bottom line question: is there any reason why my app would fail to catch the standby/suspend messages, but succeed in catching the resume messages?
This Q&A [stackoverflow.com] helped, btw, but again, the messages don't seem to be making it to my app.
My code (w/ event logging code removed for brevity):
protected override void WndProc(ref System.Windows.Forms.Message m)
{
// Power status event triggered
if (m.Msg == (int)NativeMethods.WindowMessage.WM_POWERBROADCAST)
{
// Machine is trying to enter suspended state
if (m.WParam.ToInt32() == (int)NativeMethods.WindowMessage.PBT_APMQUERYSUSPEND ||
m.WParam.ToInt32() == (int)NativeMethods.WindowMessage.PBT_APMQUERYSTANDBY)
{
// Have perms to deny this message?
if((m.LParam.ToInt32() & 0x1) != 0)
{
// If so, deny broadcast message
m.Result = new IntPtr((int)NativeMethods.WindowMessage.BROADCAST_QUERY_DENY);
}
}
return; // ?!
}
base.WndProc(ref m);
}
Try to subscribe the PowerModeChanged event:
How do I check when the computer is being put to sleep or wakes up?
It works now, for both XP and Vista. I created a stub winform app with the relevant code (could be cleaned up, obviously, but it conveys the point).
I tried this same code in a test app on my (dev) machine & on a different (test) machine (also winXP). On my machine, it continues to fail, meaning the machine goes into sleep. But on the other machine, it works! At first I thought this was a debug vs release mode issue, but that's not the case.
It seems that something is different about my dev machine, though I have no idea what it could be.
Mystery solved... sorta.
Are you running on Vista or Windows Server 2008? This page says
Could that be why you're not seeing it?
In Vista call SetThreadExecutionState to notify WPM that system is not idle.
In Windows XP/2000:
An application can return BROADCAST_QUERY_DENY to deny a PBT_APMQUERYSUSPEND or PBT_APMQUERYSUSPENDFAILED request.
MSDN: Windows XP and earlier: The system broadcasts a PBT_APMQUERYSUSPEND event to request permission to suspend system operation. The system expects each application and driver to determine whether the requested event should occur and to return TRUE if it occurs, or return BROADCAST_QUERY_DENY otherwise. Applications should not deny this request. If an application denies this request, the system broadcasts a PBT_APMQUERYSUSPENDFAILED event. This event notifies applications and drivers to continue operation as usual.
Also I don't think either PBT_APMQUERYSTANDBY or PBT_APMSTANDBY are supported in Win2K. Have you tried gloablly logging broadcast when Windows shuts down to see if they are being sent?