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\n", 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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM