もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
Windows10のときには、WM_POWERBROADCASTメッセージのPBT_POWERSETTINGCHANGEの中のPowerSettingがGUID_POWER_SAVING_STATUSのときのDataをみて、0だったらバッテリー節約を抜けた、0以外だったらバッテリー節約に入った、ということを取れていたが、どうも24H2以降ではそれがとれなくなってるっぽい。
なんでか?調べる。
「Battery Saver」と「Energy Saver」
上のドキュメントによると、どうも、
24H1以前はBattery Saver(日本語で言うとバッテリー節約)と言っていたWindowsの機能が、
24H2以降ではEnergy Saver(日本語で言うと省電力)機能になったらしい。
※「バッテリー節約」と「省電力」の日本語は上のページの「ja-jp」版より。
自宅PCがノートPCでないのでしっかり試せてないが、確かどちらもタスクトレイのアイコンで、「電池マークに葉っぱマークがつく」みたいな見え方をしてたはず。
なので、ぱっと見、24H2の「省電力」への移行と離脱も同じコードで取れるかと思ったら、同じコードではダメっぽい。
どうすれば取れるかを調べる。
「バッテリー節約」と「省電力」で使うGUID
下記のドキュメントに、節約に入る時、出るときを見るためのGUIDが載っている。
https://learn.microsoft.com/ja-jp/windows/win32/power/power-setting-guids
GUID_POWER_SAVING_STATUS のほうが、windows10のときに、バッテリー節約のIN/OUTを見るために使っていたGUID。
その下に、GUID_ENERGY_SAVER_STATUSという、見るからに「省電力」のために使いそうなGUIDがあった。
これが、24H2以降の「省電力」へのIN/OUTを見るためのGUIDっぽい。
試してみる。
試したコードでエラーが出た
GUID_ENERGY_SAVER_STATUS を使ったコードを書くと、下記のようなエラーが出た。
おそらく、自宅PCに、24H2の開発環境が入っていないからだと思われる。
(あとVisualStudioが古いっぽい)
■今の環境
10.0.22621.0(22H2)までしかない。
アップデートしてみる。
■アップデート後の環境
上記VSにアップデートして、VSInstallerで10.0.26100.0(これが24H2なのかな?)をインストールし、
C++プロジェクトのプロパティの「WindowsSDKバージョン」で「10.0.26100.0」を選択すると、エラーは消えた。
とれそうなコード
※自宅PCがノートでないので試せてない。が、MSのドキュメントからすると、下記のコードで動きそうな気がする。 動かせる環境手に入れ次第、試してみる。
#include <iostream> #include <chrono> #include "framework.h" #include "PowerSaverJikken.h" #include "resource.h" HINSTANCE hInst; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { hInst = hInstance; DialogBox(hInst, L"MyTestDlgBase_Main", NULL, (DLGPROC)MyDlgProc); return (int)0; } std::wstring getTimeStamp() { auto now = std::chrono::system_clock::now(); auto now_c = std::chrono::system_clock::to_time_t(now); tm time; auto err = localtime_s(&time, &now_c); auto timeObj = std::put_time(&time, L"%Y/%m/%d %H:%M:%S"); std::wostringstream ss; ss << timeObj; return ss.str(); } void AddMsg(HWND hDlg, std::wstring msg) { auto list = GetDlgItem(hDlg, IDC_LIST1); auto msgWithTime = getTimeStamp() + L" " + msg; SendMessage(list, LB_INSERTSTRING, (WPARAM)0, (LPARAM)msgWithTime.c_str()); } BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: { RegisterPowerSettingNotification(hDlg, &GUID_POWER_SAVING_STATUS, DEVICE_NOTIFY_WINDOW_HANDLE); RegisterPowerSettingNotification(hDlg, &GUID_ENERGY_SAVER_STATUS, DEVICE_NOTIFY_WINDOW_HANDLE); break; } case WM_POWERBROADCAST: { if (wp == PBT_POWERSETTINGCHANGE) { auto lppbc = (POWERBROADCAST_SETTING*)lp; // 24H1までの「バッテリー節約」 if (lppbc->PowerSetting == GUID_POWER_SAVING_STATUS) { if (lppbc->Data[0] == 0) AddMsg(hDlg, L"Power Saving OFF(GUID_POWER_SAVING_STATUS)"); else AddMsg(hDlg, L"Power Saving ON(GUID_POWER_SAVING_STATUS)"); } // 24H2以降の「省電力」 if (lppbc->PowerSetting == GUID_ENERGY_SAVER_STATUS) { if (lppbc->Data[0] == ENERGY_SAVER_OFF) AddMsg(hDlg, L" ENERGY_SAVER_OFF"); else if (lppbc->Data[0] == ENERGY_SAVER_STANDARD) AddMsg(hDlg, L" ENERGY_SAVER_STANDARD"); else if (lppbc->Data[0] == ENERGY_SAVER_HIGH_SAVINGS) AddMsg(hDlg, L" ENERGY_SAVER_HIGH_SAVINGS"); else AddMsg(hDlg, L" ???"); } } break; } } return FALSE; }
24/09/12 追記
試した結果、このコードで、「バッテリー節約」も「省電力」も、取ることができた。
但し、いくつか注意しないと行けないなと思った点があった。
上のコードを使うときの注意
- 2024/9月時点のwindows11 24H2で試した時点では、
GUID_POWER_SAVING_STATUS
もGUID_ENERGY_SAVER_STATUS
も、両方を通っていた。
なので、24H1以前向けのつもりでGUID_POWER_SAVING_STATUS
、24H2以降向けのつもりでGUID_ENERGY_SAVER_STATUS
、と両方を同時に書いて、 両方に「葉っぱを開始したとき」にやりたい処理を書いたりしていると、意図せず二重に処理を実施してしまう、とかになりそう。 GUID_ENERGY_SAVER_STATUS
のほうは24H2時点のWIndowsの節約のためのUIの通りに(節約の閾値をバッテリ残量が下回ったら節約に入る、とか)動いてそうだが、GUID_POWER_SAVING_STATUS
のほうは、どういう基準で「節約」に入ってるのか不明。(なにか、閾値があるのか??)
省電力の説明、何気に怖いことを書いてないか...
バックグラウンドアプリをブロックしますとか、一部タスクスケジューラを動かさないとかかれている。
何気にそういう機能を利用している場合に、アプリ動かない、とかならないか。。。。
https://learn.microsoft.com/ja-jp/windows-hardware/design/component-guidelines/energy-saver
参考
24H1以前の「バッテリー節約」と24H2以降の「省電力」について
バッテリー節約(旧)
https://learn.microsoft.com/ja-jp/windows-hardware/design/component-guidelines/battery-saver
省電力(新)
https://learn.microsoft.com/ja-jp/windows-hardware/design/component-guidelines/energy-saver
電源設定GUIDの一覧
https://learn.microsoft.com/ja-jp/windows/win32/power/power-setting-guids