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);
}
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).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace standbyTest
{
public partial class Form1 : Form
{
[DllImport("Kernel32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
protected static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE state);
[Flags]
public enum EXECUTION_STATE : uint
{
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 2,
ES_SYSTEM_REQUIRED = 1,
ES_AWAYMODE_REQUIRED = 0x00000040
}
public Form1()
{
if(Environment.OSVersion.Version.Major > 5)
{
// vista and above: block suspend mode
SetThreadExecutionState(EXECUTION_STATE.ES_AWAYMODE_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
InitializeComponent();
//MessageBox.Show(string.Format("version: {0}", Environment.OSVersion.Version.Major.ToString() ));
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if(Environment.OSVersion.Version.Major > 5)
{
// Re-allow suspend mode
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
}
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
// Power status event triggered
if(m.Msg == (int)WindowMessage.WM_POWERBROADCAST)
{
// Machine is trying to enter suspended state
if(m.WParam.ToInt32() == (int)WindowMessage.PBT_APMQUERYSUSPEND ||
m.WParam.ToInt32() == (int)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)WindowMessage.BROADCAST_QUERY_DENY);
}
}
return;
}
base.WndProc(ref m);
}
}
internal enum WindowMessage
{
/// <summary>
/// Notify that machine power state is changing
/// </summary>
WM_POWERBROADCAST = 0x218,
/// <summary>
/// Message indicating that machine is trying to enter suspended state
/// </summary>
PBT_APMQUERYSUSPEND = 0x0,
PBT_APMQUERYSTANDBY = 0x0001,
/// <summary>
/// Message to deny broadcast query
/// </summary>
BROADCAST_QUERY_DENY = 0x424D5144
}
}
Try to subscribe the PowerModeChanged event:
How do I check when the computer is being put to sleep or wakes up?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With