Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Set Lid Close Action

I wanted to automate setting the action Windows 7 takes when the lid is closed on my work laptop, as this is reset via GPO every time i login.

I know that i can use the powercfg command in a batch script to achieve this:

powercfg -setacvalueindex 5ca83367-6e45-459f-a27b-476b1d01c936 0
powercfg -setdcvalueindex 5ca83367-6e45-459f-a27b-476b1d01c936 0

However, this was a good excuse to attempt learning some powershell. My first attempt takes over 10 seconds to run.

How can i improve on the below, both in terms of runtime & in terms of cleanliness of the code. What would be the idiomatic powershell way to approach the below?

$DO_NOTHING = 0

$activePowerPlan = Get-WmiObject -Namespace "root\cimv2\power" Win32_PowerPlan | where {$_.IsActive}
$rawPowerPlanID = $activePowerPlan | select -Property InstanceID
$rawPowerPlanID -match '\\({.*})}'
$powerPlanID = $matches[1]

# The .GetRelated() method is an inefficient approach, i'm looking for a needle and this haystack is too big. Can i go directly to the object instead of searching?
$lidCloseActionOnACPower = $activePowerPlan.GetRelated("win32_powersettingdataindex") | where {$_.InstanceID -eq "Microsoft:PowerSettingDataIndex\$powerPlanID\AC\{5ca83367-6e45-459f-a27b-476b1d01c936}"}
$lidCloseActionOnBattery = $activePowerPlan.GetRelated("win32_powersettingdataindex") | where {$_.InstanceID -eq "Microsoft:PowerSettingDataIndex\$powerPlanID\DC\{5ca83367-6e45-459f-a27b-476b1d01c936}"}

$lidCloseActionOnACPower | select -Property SettingIndexValue
$lidCloseActionOnACPower.SettingIndexValue = $DO_NOTHING
$lidCloseActionOnACPower.put()

$lidCloseActionOnBattery | select -Property SettingIndexValue
$lidCloseActionOnBattery.SettingIndexValue = $DO_NOTHING
$lidCloseActionOnBattery.put()
like image 894
CraigJPerry Avatar asked Mar 16 '13 23:03

CraigJPerry


2 Answers

Honestly, I don't see any reason why you shouldn't use tools that simply work... ;) Anyways: when working with WMI is usually good idea to filter as much to the left as you can. Should not make much difference here, but at times difference is huge. This is how I would do it with WMI:

$Name = @{
    Namespace = 'root\cimv2\power'
}
$ID = (Get-WmiObject @Name Win32_PowerPlan -Filter "IsActive = TRUE") -replace '.*(\{.*})"', '$1'
$Lid = '{5ca83367-6e45-459f-a27b-476b1d01c936}'
Get-WmiObject @Name Win32_PowerSettingDataIndex -Filter "InstanceId LIKE '%$Id\\%C\\$Lid'" | 
    Set-WmiInstance -Arguments @{ SettingIndexValue = 0 }

There may be better way with more advanced WQL query, this is almost the same what you did, only bit modified.

like image 198
BartekB Avatar answered Nov 07 '22 07:11

BartekB


Try the WMI accelerator:

$class = ([wmi] '\root\cimv2\power:Win32_PowerSettingDataIndex.InstanceID="Microsoft:PowerSettingDataIndex\\{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}\\DC\\{5ca83367-6e45-459f-a27b-476b1d01c936}"')
$class.SettingIndexValue = 0
$class.Put()
like image 25
Andy Arismendi Avatar answered Nov 07 '22 07:11

Andy Arismendi