connected standby

参考链接

https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby

https://blogs.msdn.microsoft.com/winsdk/2014/12/02/how-to-get-notified-when-going-in-and-out-of-connected-standby-from-a-windows-service/

一 介绍

  低功耗联网状态, win8 win8.1叫connected standby, win10 对win8的connected standby 进行了扩展, 并起了一个新名字,叫modern-standby

  进入这种状态时,Windows Store Applications以及传统桌面程序会被暂停, session 0中的服务程序不会被暂停, 但是会受到一些限制(目前没有详细测试, 会受到哪些限制)

  只有硬件跟系统都支持的时候, 这台机器才支持这种状态

二 查看是否支持这种状态

  以win10为例, 使用命令powercfg /a之后, 如果有 so 低电量待机字样的说明当前机器支持这种状态

  

三 查看当前系统何时进入这种状态

还是以win10为例, 使用命令 powercfg /batteryreport, 成功执行后会在当前目录生成一份电池使用报告, 部分报告如下所示

四 程序感知系统进入跟离开这种状态

在第二个url中有详细的方法, 测试服务通知的时候发现有一些细节需要注意, 参见代码中的注释, 关键代码如下:

1 #include <PowrProf.h>
2 #pragma comment(lib,"PowrProf.lib")
3 #include <WinNT.h>
 1 SERVICE_STATUS_HANDLE hStatus = NULL;
 2 VOID WINAPI ServiceMain(DWORD   dwNumServicesArgs, LPWSTR  *lpServiceArgVectors)
 3 {
 4 //省略的代码
 5 
 6     
 7 //为服务注册控制处理器
 8     hStatus = RegisterServiceCtrlHandlerEx(L"aaa", Ctrlhandler, NULL);//服务名,指向controlhandlefunction指针
 9     if (!hStatus)
10     {
11         return;
12     }
13 
14 //省略的代码
15 
16     WriteLog("service start");
17     // 针对connected standby的特殊处理
18     HPOWERNOTIFY hNotify = NULL;
19     if (IsSupportConnectedStandby())
20     {
21         hNotify =RegisterPowerSettingNotification(hStatus, &GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_SERVICE_HANDLE);
22         if (!hNotify)
23             WriteLog("register err!!!!");
24         else
25             WriteLog("register success");
26     }
27 
28 
29 //省略的代码
30 
31    
32     // 服务主线程结束时, 要取消掉通知回调
33     if (hNotify)
34         UnregisterPowerSettingNotification(hNotify);
35 }
 1 bool IsSupportConnectedStandby()//S0 low power idle
 2 {
 3     bool result = false;
 4     do
 5     {
 6         SYSTEM_POWER_CAPABILITIES info = { 0 };
 7         NTSTATUS ret = CallNtPowerInformation(SystemPowerCapabilities, NULL, 0, &info, sizeof(info));
 8         if (ret != 0)//STATUS_SUCCESS 用户层没有这个宏, 所以直接用数值进行比较
 9         {
10             printf("get info error: %x
", ret);
11             break;
12         }
13         if (info.AoAc == TRUE)
14             result = true;
15     } while (false);
16 
17     return result;
18 }
  1 DWORD WINAPI Ctrlhandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
  2 {
  3     switch (dwControl)
  4     {
  5     case SERVICE_CONTROL_STOP:
  6         brun = false;
  7         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  8         WriteLog("SERVICE_CONTROL_STOP");
  9         break;
 10     case SERVICE_CONTROL_SHUTDOWN:
 11         brun = false;
 12         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
 13         WriteLog("SERVICE_CONTROL_SHUTDOWN");
 14         break;
 15     case SERVICE_CONTROL_PAUSE:
 16         brun = false;
 17         ServiceStatus.dwCurrentState = SERVICE_PAUSED;
 18         WriteLog("SERVICE_CONTROL_SHUTDOWN");
 19         break;
 20     case SERVICE_CONTROL_CONTINUE:
 21         brun = false;
 22         ServiceStatus.dwCurrentState = SERVICE_RUNNING;
 23         break;
 24     case SERVICE_CONTROL_POWEREVENT:
 25         switch (dwEventType)
 26         {
 27         case PBT_APMRESUMEAUTOMATIC:
 28         {
 29             WriteLog("PBT_APMRESUMEAUTOMATIC");
 30             break;
 31         }
 32         case PBT_APMRESUMESUSPEND:
 33         {
 34             WriteLog("PBT_APMRESUMESUSPEND");
 35             break;
 36         }
 37         case PBT_APMSUSPEND:
 38         {
 39             WriteLog("PBT_APMSUSPEND");
 40             break;
 41         }
 42         case PBT_APMPOWERSTATUSCHANGE: // 交流变电池 或者电池变交流
 43         {
 44             WriteLog("PBT_APMPOWERSTATUSCHANGE");
 45             break;
 46         }
 47         case PBT_POWERSETTINGCHANGE:
 48         {
 49             WriteLog("PBT_POWERSETTINGCHANGE");
 50             PPOWERBROADCAST_SETTING setting = (PPOWERBROADCAST_SETTING)lpEventData;
 51             if(setting->PowerSetting == GUID_MONITOR_POWER_ON)
 52             {
 53                 std::string str("GUID_MONITOR_POWER_ON ");
 54 
 55                 if(setting->DataLength == 4)
 56                 {
 57                     // MONITOR_POWER_OFF(data ==0)-->进入 connected standby状态
 58                     // MONITOR_POWER_ON(data ==1)-->进入 active状态
 59                     // MONITOR_POWER_OFF对应于设置里面睡眠进入的时间, 而不是根据字面意思对应设置里面的屏幕关闭时间, 这个要注意!!!
 60                     // 刚刚注册GUID_MONITOR_POWER_ON成功后会立刻收到一次该事件, 报告data ==1
 61                     DWORD data = *(DWORD*)(setting->Data);
 62                     str += std::to_string(data);
 63                 }
 64                 else
 65                 {
 66                     str += "len: ";
 67                     str += std::to_string(setting->DataLength);
 68                 }
 69                 WriteLog(str);
 70             }
 71             break;
 72         }
 73 
 74         default:
 75             break;
 76         }
 77         break;
 78     case SERVICE_CONTROL_SESSIONCHANGE:
 79     {
 80         std::string str("SERVICE_CONTROL_SESSIONCHANGE: ");
 81         str+= std::to_string(dwEventType);
 82         
 83         PWTSSESSION_NOTIFICATION Notification = (PWTSSESSION_NOTIFICATION)lpEventData;
 84         str += " ";
 85         str += std::to_string(Notification->dwSessionId);
 86         WriteLog(str.c_str());
 87 
 88         switch (dwEventType)
 89         {
 90         case WTS_CONSOLE_CONNECT:
 91             break;
 92         case WTS_CONSOLE_DISCONNECT:
 93             break;
 94         case WTS_SESSION_LOGON:
 95             break;
 96         case WTS_SESSION_LOGOFF:
 97             break;
 98         case WTS_SESSION_LOCK:
 99             break;
100         case WTS_SESSION_UNLOCK:
101             break;
102         default:
103             ;
104         }
105     }
106         break;
107     default:
108         break;
109     }
110     //向SCM报告“SERVICE_STOPPED”状态
111     SetServiceStatus(hStatus, &ServiceStatus);
112     return NO_ERROR;
113 }
原文地址:https://www.cnblogs.com/talenth/p/10503726.html