zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    伺服电机常见故障分析汇总
    PLC常见四大故障及其处理方法
    Qt QString的arg()方法的使用
    Qt 线程池QThreadPool类、QRunnable类
    C++线程池的实现
    C++ List的用法
    C++语言堆栈的详细讲解
    QT中的QQueue类、C++中的queue类
    Qt platform plugin 'windows' 问题的解决方法
    电气接地的相关介绍
  • 原文地址:https://www.cnblogs.com/talenth/p/10503726.html
Copyright © 2011-2022 走看看