今天想写个小程序记录每天电脑实际工作时间,由此需要捕获系统睡眠,唤醒的通知事件。查询了一下可以通过api PowerRegisterSuspendResumeNotification
实现这功能。
进一步搜索了下,stackoverflow上有现成的封装代码 , 就基于它的代码简单的改了下:
public class PowerEvent
{
public static void Regist()
{
var registrationHandle = new IntPtr();
var recipient = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
{
Callback = DeviceNotifyCallback,
Context = IntPtr.Zero
};
var pRecipient = Marshal.AllocHGlobal(Marshal.SizeOf(recipient));
Marshal.StructureToPtr(recipient, pRecipient, false);
var result =
PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, ref recipient, ref registrationHandle);
if (result != 0)
Console.WriteLine("Error registering for power notifications: " + Marshal.GetLastWin32Error());
else
Console.WriteLine("Successfully Registered for power notifications!");
Console.ReadKey();
}
private static int DeviceNotifyCallback(IntPtr context, int type, IntPtr setting)
{
Console.WriteLine(
$"\n\n{DateTime.Now}: Device notify callback called: context: {context},type: {type}, setings: {setting}");
switch (type)
{
case PBT_APMPOWERSTATUSCHANGE:
Console.WriteLine("\tPower status has changed.");
break;
case PBT_APMRESUMEAUTOMATIC:
Console.WriteLine(
"\tOperation is resuming automatically from a low-power state.This message is sent every time the system resumes.");
break;
case PBT_APMRESUMESUSPEND:
Console.WriteLine(
"\tOperation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.");
break;
case PBT_APMSUSPEND:
Console.WriteLine("\tSystem is suspending operation.");
break;
case PBT_POWERSETTINGCHANGE:
Console.WriteLine("\tA power setting change event has been received. ");
break;
default:
Console.WriteLine("unknown");
break;
}
// do something here
return 0;
}
[DllImport("Powrprof.dll", SetLastError = true)]
static extern uint PowerRegisterSuspendResumeNotification(
uint flags, ref DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS receipient, ref IntPtr registrationHandle);
private const int WM_POWERBROADCAST = 536; // (0x218)
private const int PBT_APMPOWERSTATUSCHANGE = 10; // (0xA) - Power status has changed.
private const int
PBT_APMRESUMEAUTOMATIC =
18; // (0x12) - Operation is resuming automatically from a low-power state.This message is sent every time the system resumes.
private const int
PBT_APMRESUMESUSPEND =
7; // (0x7) - Operation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
private const int PBT_APMSUSPEND = 4; // (0x4) - System is suspending operation.
private const int PBT_POWERSETTINGCHANGE = 32787; // (0x8013) - A power setting change event has been received.
private const int DEVICE_NOTIFY_CALLBACK = 2;
/// <summary>
/// OS callback delegate definition
/// </summary>
/// <param name="context">The context for the callback</param>
/// <param name="type">The type of the callback...for power notifcation it's a PBT_ message</param>
/// <param name="setting">A structure related to the notification, depends on type parameter</param>
/// <returns></returns>
delegate int DeviceNotifyCallbackRoutine(IntPtr context, int type, IntPtr setting);
/// <summary>
/// A callback definition
/// </summary>
[StructLayout(LayoutKind.Sequential)]
struct DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
{
public DeviceNotifyCallbackRoutine Callback;
public IntPtr Context;
}
}
参考文章: windows - C#, SystemEvents.PowerModeChanged event is not raised on sleep or resume - Stack Overflow