我有一個在 .net 4.5(僅限)上運行的控制臺應用程式。我試圖檢測計算機何時從睡眠/休眠模式回傳。我嘗試使用,Win32.SystemEvents.PowerModeChanged但由于某種原因它不起作用......我正在使用運行 Windows 10 的 ThinkPad 筆記本電腦,當我拔下充電線時,它確實使用引數 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");
}
}
嘗試列印到螢屏并寫入檔案,無法讓它作業......
請如果有人有想法或不同的方法,最后我需要趕上計算機從睡眠或休眠狀態回傳的時間。
uj5u.com熱心網友回復:
解決了:
從 Windows 10 開始,微軟添加了現代待機,擴展了 Windows 8.1 連接待機電源模型。
SystemEvents.PowerModeChanged在 .net 4.5 中僅支持傳統睡眠和休眠 (S1-4)。
從 Windows 10 開始,2004 版現代待機是強制的并且無法禁用,SystemEvents.PowerModeChanged在我的情況下變得無用。
此處參考了用于處理現代待機電源模式更改的新 Win32 API: PowerRegisterSuspendResumeNotification 函式 MSDN
不幸的是,我沒有設法為新 API 找到完整的 C# 實作。
秀我做了一個自己用C#封裝器User32.dll,并PowrPorf.dll從Vanara專案通過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只會在進入休眠模式時觸發,而不是在現代待機睡眠/監視器關閉時觸發。
您需要注冊到RegisterPowerSettingNotification此處參考的不同通知:Registering for Power Events MSDN
and when a PowerEventcheck the monitor state。請記住,即使計算機在未進入睡眠模式的情況下進入 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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/380111.html
上一篇:錯誤:“struct_DDSURFACEDESC2”沒有名為“DUMMYUNIONNAMEN”的成員
下一篇:如何驗證用戶登錄和PIN
