Introduction
This article provides a way for a .NET Windows application to respond to Windows Power Management events such as suspend, hibernate, standby, power switch, etc.
Background
My organization uses Lotus Notes as an email client which hangs badly on our laptops when we go from one meeting room to another since the network breaks between the meeting rooms. And since Lotus Notes continuously monitors the network for any incoming mail, it tends to get hung up taking the whole window down with it. So to avoid forcefully restarting Windows, I created this application to capture the standby event and close the mail client before going to standby and automatically start the mail client when the system resumes. I got a lot of reference help from the following article:
Using the Code
We need to override the WndProc
method which will allow us to interact with all the events that the OS tends to provide to the application on different conditions.
The Windows OS communicates with the application by sending different messages which need to be captured and worked on. For this implementation, we need to capture the WM_POWERBROADCAST
(0x0218) value which will specify that this is a power event change and that we need to capture the WParam
which can have the following values:
PBT_APMQUERYSUSPEND
(0x0000) PBT_APMRESUMESUSPEND
(0x0007) PBT_APMQUERYSTANDBY
(0x0001) PBT_APMQUERYSUSPENDFAILED
(0x0002) PBT_APMQUERYSTANDBYFAILED
(0x0003) PBT_APMSUSPEND
(0x0004) PBT_APMSTANDBY
(0x0005) PBT_APMRESUMECRITICAL
(0x0006) PBT_APMRESUMESTANDBY
(0x0008) PBTF_APMRESUMEFROMFAILURE
(0x00000001) PBT_APMBATTERYLOW
(0x0009) PBT_APMPOWERSTATUSCHANGE
(0x000A) PBT_APMOEMEVENT
(0x000B) PBT_APMRESUMEAUTOMATIC
(0x0012)
These values will help us to manage the application data when a power management event occurs. More details of the messages passed to the application are available at this link.
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_POWERBROADCAST:
switch (m.WParam.ToInt32())
{
case PBT_APMQUERYSUSPEND:
List<string> arr =
Properties.Settings.Default.StandDownApps.Split(',').ToList();
foreach (string item in arr)
{
foreach (Process p in
System.Diagnostics.Process.GetProcessesByName(item))
{
try
{
p.Kill();
p.WaitForExit(3600000);
}
catch
{
}
}
}
break;
case PBT_APMRESUMESUSPEND:
arr = Properties.Settings.Default.StandUpApps.Split(',').ToList();
foreach (string item in arr)
{
System.Diagnostics.Process.Start(item);
}
break;
case (PBT_APMQUERYSUSPENDFAILED):
case (PBT_APMSUSPEND):
case (PBT_APMRESUMEAUTOMATIC):
case (PBT_APMRESUMECRITICAL):
case (PBT_APMBATTERYLOW):
case (PBT_APMPOWERSTATUSCHANGE):
case (PBT_APMOEMEVENT):
break;
}
break;
default:
break;
}
base.WndProc(ref m);
}
Points of Interest
The main learning point was how to capture the events for standby, suspend, and resume of Windows which will be useful to gracefully handle these kinds of events to prevent data from getting corrupted.
History
- Version 1.0 - Initial draft (5th May 2011)
I have been working in software industry for the past 11 years, though i am trained to be a pharmacist. Enjoy working on complex and new technologies. Also cleared my SCJP and MCP certification examinations.