PowerShell/WMI power management

HairOfTheDog picture HairOfTheDog · Feb 10, 2016 · Viewed 7.6k times · Source

I'm new to Windows power management and even newer to WMI, but always welcome a learning opportunity.

Using PowerShell and WMI I want to set the "High Performance" power plan's "Lid close action", "Power button action" and "Sleep button action" to the "Do nothing" option and finally set the active power plan to the "High Performance" power plan. I have a working solution, but I have my doubts as to whether it is a proper solution.

The crux of my problem is that all of the plans, subgroups, actions, available values, etc. are identified with GUIDs and I've read that it is possible for these GUIDs to vary from system to system (especially if applied via group policy.) In my solution I've managed to avoid hard coding GUIDs only to end up hard coding values such as "Power and lid buttons", "Lid close action", "Do nothing", etc. which may or may not vary in non-English builds of Windows. (I'm using Windows 8.1 by the way.)

My question

What's the proper way to programmatically discover the GUID for each plan, subgroup, action, available value, etc?

Reference

In BATCH using the powercfg.exe tool the commands would be:

:: Set the lid close action, power button action and sleep button action to do nothing

powercfg /SETACVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 0
powercfg /SETDCVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 0
powercfg /SETACVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 0
powercfg /SETDCVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 0
powercfg /SETACVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb 0
powercfg /SETDCVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb 0
powercfg /SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

My PowerShell/WMI solution is this:

$CommonArgs = @{"namespace"="root\cimv2\power"}
$CommonArgs += $PSBoundParameters

function Set-PowerSettingDataIndexValue
{
    <#
    .Synopsis
        Sets the value associated with a specified power setting for both AC and DC power.
    .Description
        This function is somewhat similar to running the two commands
        'POWERCFG /SETACVALUEINDEX <SCHEME_GUID> <SUB_GUID> <SETTING_GUID> <SETTING_INDEX>'
        and
        'POWERCFG /SETDCVALUEINDEX <SCHEME_GUID> <SUB_GUID> <SETTING_GUID> <SETTING_INDEX>'
        except that the <SUB_GUID> is implied by the $PowerSettingDefinitionGuid
    .Example
        Set-PowerSettingDataIndexValue "{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}" "{7648efa3-dd9c-4e3e-b566-50f929386280}" 3
    #>

    [CmdletBinding()]
    param (
        [parameter(Mandatory=$true)]
        [string]$PowerPlanGuid,
        [parameter(Mandatory=$true)]
        [string]$PowerSettingDefinitionGuid,
        [parameter(Mandatory=$true)]
        [string]$SettingIndexValue
    )

    $PowerSettingDataIndexAC = Get-CimInstance -ClassName Win32_PowerSettingDataIndex -Filter "InstanceID = 'Microsoft:PowerSettingDataIndex\\$PowerPlanGuid\\AC\\$PowerSettingDefinitionGuid'" @CommonArgs
    Set-CimInstance -InputObject $PowerSettingDataIndexAC -Property @{ SettingIndexValue=$SettingIndexValue }

    $PowerSettingDataIndexDC = Get-CimInstance -ClassName Win32_PowerSettingDataIndex -Filter "InstanceID = 'Microsoft:PowerSettingDataIndex\\$PowerPlanGuid\\DC\\$PowerSettingDefinitionGuid'" @CommonArgs
    Set-CimInstance -InputObject $PowerSettingDataIndexDC -Property @{ SettingIndexValue=$SettingIndexValue }
}

function Set-PowerButtonAndLidActions
{
    <#
    .Synopsis
        Sets the power button, sleep button and lid actions to do nothing effectively disabling these buttons.
    .Description
        This function modifies every existing power plan to effectively disable the power button, sleep button and
        lid action. Additonally this function will set the "high performance" power plan as the active power plan.
    .Example
        Set-PowerButtonAndLidActions
    #>

    # Get the power setting subgroup where the element name is 'Power buttons and lid'
    $PowerSettingSubgroup = Get-CimInstance -ClassName Win32_PowerSettingSubgroup -Filter "ElementName = 'Power buttons and lid'" @CommonArgs

    # Get the power setting definitions for 'Lid close action', 'Power button action' and 'Sleep button action'
    $PowerSettingDefinitionLidCloseAction = Get-CimAssociatedInstance -InputObject $PowerSettingSubgroup | where { $_.ElementName -eq "Lid close action" }
    $PowerSettingDefinitionPowerButtonAction = Get-CimAssociatedInstance -InputObject $PowerSettingSubgroup | where { $_.ElementName -eq "Power button action" }
    $PowerSettingDefinitionSleepButtonAction = Get-CimAssociatedInstance -InputObject $PowerSettingSubgroup | where { $_.ElementName -eq "Sleep button action" }

    # Extract the GUID from each action's instance ID
    $PowerSettingDefinitionLidCloseActionGuid = $PowerSettingDefinitionLidCloseAction.InstanceID -replace '.*({[^}]+})', '$1'
    $PowerSettingDefinitionPowerButtonActionGuid = $PowerSettingDefinitionPowerButtonAction.InstanceID -replace '.*({[^}]+})', '$1'
    $PowerSettingDefinitionSleepButtonActionGuid = $PowerSettingDefinitionSleepButtonAction.InstanceID -replace '.*({[^}]+})', '$1'

    # Get the value of the 'Do Nothing' option for each power setting definition
    $LidCloseActionDoNothing = Get-CimInstance -Query "SELECT * FROM Win32_PowerSettingDefinitionPossibleValue WHERE ElementName = 'Do nothing' AND InstanceID LIKE '%\\$PowerSettingDefinitionLidCloseActionGuid\\%'" @CommonArgs
    $PowerButtonActionDoNothing = Get-CimInstance -Query "SELECT * FROM Win32_PowerSettingDefinitionPossibleValue WHERE ElementName = 'Do nothing' AND InstanceID LIKE '%\\$PowerSettingDefinitionPowerButtonActionGuid\\%'" @CommonArgs
    $SleepButtonActionDoNothing = Get-CimInstance -Query "SELECT * FROM Win32_PowerSettingDefinitionPossibleValue WHERE ElementName = 'Do nothing' AND InstanceID LIKE '%\\$PowerSettingDefinitionSleepButtonActionGuid\\%'" @CommonArgs

    $p = Get-CimInstance -ClassName Win32_PowerPlan -Filter "ElementName = 'High performance'" @CommonArgs

    # Extract the GUID from the power plan's InstanceID property
    $PlanGuid = $p.InstanceID -replace '.*({[^}]+})', '$1'

    Set-PowerSettingDataIndexValue -PowerPlanGuid $PlanGuid -PowerSettingDefinitionGuid $PowerSettingDefinitionLidCloseActionGuid $LidCloseActionDoNothing.SettingIndex
    Set-PowerSettingDataIndexValue -PowerPlanGuid $PlanGuid -PowerSettingDefinitionGuid $PowerSettingDefinitionPowerButtonActionGuid $PowerButtonActionDoNothing.SettingIndex
    Set-PowerSettingDataIndexValue -PowerPlanGuid $PlanGuid -PowerSettingDefinitionGuid $PowerSettingDefinitionSleepButtonActionGuid $SleepButtonActionDoNothing.SettingIndex

    Invoke-CimMethod -InputObject $p -MethodName Activate | Out-Null
}

Set-PowerButtonAndLidActions

Answer

TheMadTechnician picture TheMadTechnician · Feb 11, 2016

You can use Get-CIMInstance to list pretty much all of these. The power plans are all in the Win32_PowerPlan class, so:

Get-CimInstance -classname Win32_PowerPlan -Namespace "root\cimv2\power"

That will list all of the plans on the computer. You can find all this information at https://msdn.microsoft.com/en-us/library/dd904531(v=vs.85).aspx. There's even PowerShell examples.

From there you just have to parse out the info that you need. The ElementName property shows what somebody would see if they went to the Power Settings GUI in the control panel. The InstanceID is where you'll find the GUID, though you may need to do something like:

Get-CimInstance -Namespace "root\cimv2\power" -class Win32_PowerPlan|Select ElementName,@{l='GUID';e={$_.instanceid.substring(20)}}

The rest should be found in Win32_PowerSetting and Win32_PowerSettingSubgroup. You should be able to explore that site to find other related classes to get you what info you need.