PowerShellで電源スリープ設定が有効かどうか確認する


電源スリープ設定が有効かどうかを確認する処理をPowerShellで書いたので貼っておきます。

えーっと、すごい煩雑です。
解説はスクリプト内にコメントで書いておいたのだけど、電源関連の設定はWMI経由で `root/CIMV2/power` の `Win32_PowerPlanか` ら電源プランの情報を取得し、 `Win32_PowerSettingDataIndex` から設定値の情報を取得します。
「次の時間が経過後スリープする」と「復帰時のパスワードを必要とする」の設定項目の `InstanceID` を決め打ちで指定している箇所があるのだけど、検証に使った複数のPCで同じ値になってたので、個体差はなさそうなんだけど、すべての端末やWindowsバージョンで同じなのかどうかは不明。レジストリキーっぽい香りがしてあんまり綺麗ではない。

```ps1
function SubCheck-PowerSleep($sleepThresholdSec){
    # WMI経由で電源関連の設定値を取得する
    # root/CIMV2/powerのWin32_PowerPlanから電源プランの情報
    # Win32_PowerSettingDataIndexから設定値の情報を取得する
    # Win32_PowerSettingDataIndexのInstanceIDはプランのInstanceIDと設定項目のInstanceIDから導出できる
    # 設定項目のInstanceIDはWin32_PowerSettingからElementName指定で取得できるが言語設定に依存するため問題あり
    # 設定項目のInstanceIDは検証に使用したVirtualBoxのWindows8.1/7とVAIOのWindows8.1で同じで、
    # 端末やバージョンごとに異なるわけではないようなのでとりあえず決め打ちする

    # 現在の電源プランを取得
    # デフォルトは「バランス」だが、選択中の電源プランによってInstanceIDが異なるため、現在使用しているプランを取得する
    # InstanceID     : Microsoft:PowerPlan\{381b4222-f694-41f0-9685-ff5bb260df2e}
    $powerPlan = Get-WMIObject -Namespace "root/CIMV2/power" -Query "SELECT * FROM Win32_PowerPlan WHERE IsActive = true"

    $powerSleep = @{}

    # 設定値が取得できなかった場合
    if (!$powerPlan) {
        $powerSleep["PowerSleepCheckStatus"] = "NG"
        return $powerSleep
    }

    $powerSleep["PowerPlanInstanceID"] = $powerPlan.InstanceID

    # InstanceID末尾のUUID部分を切り出す
    $powerPlanUUID = $powerPlan.InstanceID.Split('\')[1]

    # スリープタイムアウト時間の設定項目(次の時間が経過後スリープする)
    $powerSettingTimeoutUUID = "{29f6c1db-86da-48c5-9fdb-f2b67b1f44da}"

    # スリープ解除時のパスワード保護の設定項目(復帰時のパスワードを必要とする)
    $powerSettingSecureUUID = "{0e796bdb-100d-47d6-a2d5-f7d2daa51f51}"

    # Win32_PowerSettingDataIndexのInstanceIDを以下のルールで導出
    # DCはバッテリ駆動、ACは電源接続でそれぞれ分かれているので両方
    $powerSettingDataIndexTimeoutDCInsntaceID = "Microsoft:PowerSettingDataIndex\\" + $powerPlanUUID + "\\DC\\" + $powerSettingTimeoutUUID
    $powerSettingDataIndexTimeoutACInsntaceID = "Microsoft:PowerSettingDataIndex\\" + $powerPlanUUID + "\\AC\\" + $powerSettingTimeoutUUID
    $powerSettingDataIndexSecureDCInsntaceID = "Microsoft:PowerSettingDataIndex\\" + $powerPlanUUID + "\\DC\\" + $powerSettingSecureUUID
    $powerSettingDataIndexSecureACInsntaceID = "Microsoft:PowerSettingDataIndex\\" + $powerPlanUUID + "\\AC\\" + $powerSettingSecureUUID

    # 設定値を取得する
    $powerSleep["PowerSettingTimeoutDC"] = (Get-WMIObject -Namespace "root/CIMV2/power" -Query "SELECT * FROM Win32_PowerSettingDataIndex WHERE InstanceID = ""$powerSettingDataIndexTimeoutDCInsntaceID""").SettingIndexValue
    $powerSleep["PowerSettingTimeoutAC"] = (Get-WMIObject -Namespace "root/CIMV2/power" -Query "SELECT * FROM Win32_PowerSettingDataIndex WHERE InstanceID = ""$powerSettingDataIndexTimeoutACInsntaceID""").SettingIndexValue
    $powerSleep["PowerSettingSecureDC"] = (Get-WMIObject -Namespace "root/CIMV2/power" -Query "SELECT * FROM Win32_PowerSettingDataIndex WHERE InstanceID = ""$powerSettingDataIndexSecureDCInsntaceID""").SettingIndexValue
    $powerSleep["PowerSettingSecureAC"] = (Get-WMIObject -Namespace "root/CIMV2/power" -Query "SELECT * FROM Win32_PowerSettingDataIndex WHERE InstanceID = ""$powerSettingDataIndexSecureACInsntaceID""").SettingIndexValue

    # チェック判定
    # タイムアウト時間は引数で指定された閾値以下であるかどうか（ただし適用しないで無効化した場合は0となるので0も不可）
    # 復帰時のパスワードは必要（必要な場合は1、不要な場合は0がセットされている）
    if ( ($powerSleep["PowerSettingTimeoutDC"] -gt 0) -and ($powerSleep["PowerSettingTimeoutDC"] -le $sleepThresholdSec) -and
         ($powerSleep["PowerSettingTimeoutAC"] -gt 0) -and ($powerSleep["PowerSettingTimeoutAC"] -le $sleepThresholdSec) -and
         ($powerSleep["PowerSettingSecureDC"] -eq 1) -and
         ($powerSleep["PowerSettingSecureAC"] -eq 1) ) {
        $powerSleep["PowerSleepCheckStatus"] = "OK"
    } else {
        $powerSleep["PowerSleepCheckStatus"] = "NG"
    }

    return $powerSleep
}
```