当计算机从 sleep/hibernate 模式恢复时,如何捕获事件?
How can I catch an event when the computer resume from sleep/hibernate mode?
我在 .net 4.5(仅)上有一个控制台应用程序 运行。
我正在尝试检测计算机何时从 sleep/hibernate 模式进入 return。
我尝试使用 Win32.SystemEvents.PowerModeChanged
但由于某种原因它不起作用......
我正在使用 ThinkPad 笔记本电脑 运行 windows 10,当我拔下充电线时,它确实会触发带有参数 Mode = PowerModes.StatusChange
.
的事件
class Program
{
static void Main(string[] args)
{
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
Console.WriteLine("This application is waiting for system events.");
Console.WriteLine("Press <Enter> to terminate this application.");
Console.ReadLine();
}
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
Console.WriteLine(Enum.GetName(typeof(PowerModes), e.Mode));
File.WriteAllText("test.txt", "test");
}
}
尝试打印到屏幕并写入文件,但无法正常工作...
请如果有人有想法或不同的方法,最后我需要赶上计算机 return 从睡眠或休眠状态。
已解决:
从 windows 10 开始,微软添加了 Modern Standby 扩展了 Windows 8.1 Connected Standby 电源模型。
SystemEvents.PowerModeChanged
在 .net 4.5 中仅支持传统睡眠和休眠 (S1-4)。
从 windows10 开始,2004 版 Modern Standby 被强制执行且无法禁用,在我的情况下呈现 SystemEvents.PowerModeChanged
无用。
此处引用了用于处理现代待机电源模式更改的新 Win32 API:
PowerRegisterSuspendResumeNotification function MSDN
不幸的是,我没能找到新 API 的完整 C# 实现。
所以我自己用 C# 包装器为 Vanara Project By dahall (GitHub) 和 PowrPorf.dll
制作了一个 Vanara Project By dahall (GitHub):
public static class SystemPowerNotifications
{
public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_eventHandler == null)
{
var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _eventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception();
}
}
remove
{
_powerModeChanged -= value;
if(_powerModeChanged.GetInvocationList().Length == 0)
{
if (PowrProf.PowerUnregisterSuspendResumeNotification(_eventHandler) != Win32Error.NO_ERROR)
throw new Exception();
_eventHandler.Dispose();
_eventHandler = null;
}
}
}
private static PowrProf.SafeHPOWERNOTIFY _eventHandler;
private static PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS _dnsp = new PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
{
Callback = OnDeviceNotify,
Context = IntPtr.Zero
};
private static Win32Error OnDeviceNotify(IntPtr context, uint type, IntPtr setting)
{
_powerModeChanged?.Invoke(null,new PowerNotificationArgs((PowerBroadcastType)type));
return 0;
}
private static SystemPowerNotificationEventHandler _powerModeChanged;
}
完整源代码:
SystemPowerModeNotification-dotnet4.5 (GitHub)
编辑:
在 Windows 服务中使用它时,在 PowerRegisterSuspendResumeNotification
中注册的回调函数只会在进入休眠模式时触发,而不会在现代待机模式下触发 Sleep/Monitor 关闭。
您需要注册到此处引用的名为 RegisterPowerSettingNotification
的不同通知:Registering for Power Events MSDN
当 PowerEvent
检查监视器状态时。
请记住,即使计算机将进入 Monitor Off/On 状态而不进入睡眠模式,它也会发生。
注册示例:
public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_powerEventHandler == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (_ssh.IsNull)
_ssh = AdvApi32.RegisterServiceCtrlHandlerEx(ServiceName, OnDisplayNotify);
if (_ssh.IsNull)
throw new Exception("Failed To Register ServiceCtrlHandlerEx");
_displayEventHandler = User32.RegisterPowerSettingNotification(((IntPtr)_ssh), PowrProf.GUID_MONITOR_POWER_ON, User32.DEVICE_NOTIFY.DEVICE_NOTIFY_SERVICE_HANDLE);
if (_displayEventHandler.IsNull)
throw new Exception("Failed To Register PowerSettingNotification");
}
var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _powerEventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception("Failed To Register PowerSuspendResumeNotification");
}
}
remove
{
_powerModeChanged -= value;
if (_powerModeChanged == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (!User32.UnregisterPowerSettingNotification(_displayEventHandler))
throw new Exception("Failed To Unregister PowerSettingNotification");
_displayEventHandler.Dispose();
_displayEventHandler = null;
}
if (PowrProf.PowerUnregisterSuspendResumeNotification(_powerEventHandler) != Win32Error.NO_ERROR)
throw new Exception("Failed To Unregister PowerSuspendResumeNotification");
_powerEventHandler.Dispose();
_powerEventHandler = null;
}
}
}
回调示例:
private static Win32Error OnDisplayNotify(AdvApi32.ServiceControl control,uint eventType,IntPtr eventData,IntPtr context)
{
var dataHandle = new HANDLE(eventData);
var contextHandle = new HANDLE(context);
if(control == AdvApi32.ServiceControl.SERVICE_CONTROL_POWEREVENT)
{
POWERBRODCAST_SETTING settings = (POWERBRODCAST_SETTING)Marshal.PtrToStructure(eventData, typeof(POWERBRODCAST_SETTING));
_powerModeChanged?.Invoke(null, new PowerNotificationArgs((PowerBroadcastType)eventType,settings.Data));
}
return 0;
}
我在 .net 4.5(仅)上有一个控制台应用程序 运行。
我正在尝试检测计算机何时从 sleep/hibernate 模式进入 return。
我尝试使用 Win32.SystemEvents.PowerModeChanged
但由于某种原因它不起作用......
我正在使用 ThinkPad 笔记本电脑 运行 windows 10,当我拔下充电线时,它确实会触发带有参数 Mode = PowerModes.StatusChange
.
class Program
{
static void Main(string[] args)
{
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
Console.WriteLine("This application is waiting for system events.");
Console.WriteLine("Press <Enter> to terminate this application.");
Console.ReadLine();
}
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
Console.WriteLine(Enum.GetName(typeof(PowerModes), e.Mode));
File.WriteAllText("test.txt", "test");
}
}
尝试打印到屏幕并写入文件,但无法正常工作...
请如果有人有想法或不同的方法,最后我需要赶上计算机 return 从睡眠或休眠状态。
已解决:
从 windows 10 开始,微软添加了 Modern Standby 扩展了 Windows 8.1 Connected Standby 电源模型。
SystemEvents.PowerModeChanged
在 .net 4.5 中仅支持传统睡眠和休眠 (S1-4)。
从 windows10 开始,2004 版 Modern Standby 被强制执行且无法禁用,在我的情况下呈现 SystemEvents.PowerModeChanged
无用。
此处引用了用于处理现代待机电源模式更改的新 Win32 API: PowerRegisterSuspendResumeNotification function MSDN
不幸的是,我没能找到新 API 的完整 C# 实现。
所以我自己用 C# 包装器为 Vanara Project By dahall (GitHub) 和 PowrPorf.dll
制作了一个 Vanara Project By dahall (GitHub):
public static class SystemPowerNotifications
{
public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_eventHandler == null)
{
var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _eventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception();
}
}
remove
{
_powerModeChanged -= value;
if(_powerModeChanged.GetInvocationList().Length == 0)
{
if (PowrProf.PowerUnregisterSuspendResumeNotification(_eventHandler) != Win32Error.NO_ERROR)
throw new Exception();
_eventHandler.Dispose();
_eventHandler = null;
}
}
}
private static PowrProf.SafeHPOWERNOTIFY _eventHandler;
private static PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS _dnsp = new PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
{
Callback = OnDeviceNotify,
Context = IntPtr.Zero
};
private static Win32Error OnDeviceNotify(IntPtr context, uint type, IntPtr setting)
{
_powerModeChanged?.Invoke(null,new PowerNotificationArgs((PowerBroadcastType)type));
return 0;
}
private static SystemPowerNotificationEventHandler _powerModeChanged;
}
完整源代码: SystemPowerModeNotification-dotnet4.5 (GitHub)
编辑:
在 Windows 服务中使用它时,在 PowerRegisterSuspendResumeNotification
中注册的回调函数只会在进入休眠模式时触发,而不会在现代待机模式下触发 Sleep/Monitor 关闭。
您需要注册到此处引用的名为 RegisterPowerSettingNotification
的不同通知:Registering for Power Events MSDN
当 PowerEvent
检查监视器状态时。
请记住,即使计算机将进入 Monitor Off/On 状态而不进入睡眠模式,它也会发生。
注册示例:
public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_powerEventHandler == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (_ssh.IsNull)
_ssh = AdvApi32.RegisterServiceCtrlHandlerEx(ServiceName, OnDisplayNotify);
if (_ssh.IsNull)
throw new Exception("Failed To Register ServiceCtrlHandlerEx");
_displayEventHandler = User32.RegisterPowerSettingNotification(((IntPtr)_ssh), PowrProf.GUID_MONITOR_POWER_ON, User32.DEVICE_NOTIFY.DEVICE_NOTIFY_SERVICE_HANDLE);
if (_displayEventHandler.IsNull)
throw new Exception("Failed To Register PowerSettingNotification");
}
var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _powerEventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception("Failed To Register PowerSuspendResumeNotification");
}
}
remove
{
_powerModeChanged -= value;
if (_powerModeChanged == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (!User32.UnregisterPowerSettingNotification(_displayEventHandler))
throw new Exception("Failed To Unregister PowerSettingNotification");
_displayEventHandler.Dispose();
_displayEventHandler = null;
}
if (PowrProf.PowerUnregisterSuspendResumeNotification(_powerEventHandler) != Win32Error.NO_ERROR)
throw new Exception("Failed To Unregister PowerSuspendResumeNotification");
_powerEventHandler.Dispose();
_powerEventHandler = null;
}
}
}
回调示例:
private static Win32Error OnDisplayNotify(AdvApi32.ServiceControl control,uint eventType,IntPtr eventData,IntPtr context)
{
var dataHandle = new HANDLE(eventData);
var contextHandle = new HANDLE(context);
if(control == AdvApi32.ServiceControl.SERVICE_CONTROL_POWEREVENT)
{
POWERBRODCAST_SETTING settings = (POWERBRODCAST_SETTING)Marshal.PtrToStructure(eventData, typeof(POWERBRODCAST_SETTING));
_powerModeChanged?.Invoke(null, new PowerNotificationArgs((PowerBroadcastType)eventType,settings.Data));
}
return 0;
}