I am trying to use powershell to query some Windows power settings from the output of powercfg
. I have enough information to narrow down the range to a subgroup of settings, but within the text block I still need to find a matching setting using a GUID, and then I need to extract the currently set value of the setting. I was able to achieve this using Select-String -Context
, but it's not dynamic and thus error-prone. I am looking for a cleaner way to extract the value.
Here is a sample of the text block I have (stored in $block
):
Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)
GUID Alias: SCHEME_BALANCED
Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20 (Sleep)
GUID Alias: SUB_SLEEP
Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da (Sleep after)
GUID Alias: STANDBYIDLE
Minimum Possible Setting: 0x00000000
Maximum Possible Setting: 0xffffffff
Possible Settings increment: 0x00000001
Possible Settings units: Seconds
Current AC Power Setting Index: 0x00000708
Current DC Power Setting Index: 0x00000384
Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e (Allow hybrid sleep)
GUID Alias: HYBRIDSLEEP
Possible Setting Index: 000
Possible Setting Friendly Name: Off
Possible Setting Index: 001
Possible Setting Friendly Name: On
Current AC Power Setting Index: 0x00000001
Current DC Power Setting Index: 0x00000001
Power Setting GUID: 9d7815a6-7ee4-497e-8888-515a05f02364 (Hibernate after)
GUID Alias: HIBERNATEIDLE
Minimum Possible Setting: 0x00000000
Maximum Possible Setting: 0xffffffff
Possible Settings increment: 0x00000001
Possible Settings units: Seconds
Current AC Power Setting Index: 0x00002a30
Current DC Power Setting Index: 0x00002a30
Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d (Allow wake timers)
GUID Alias: RTCWAKE
Possible Setting Index: 000
Possible Setting Friendly Name: Disable
Possible Setting Index: 001
Possible Setting Friendly Name: Enable
Possible Setting Index: 002
Possible Setting Friendly Name: Important Wake Timers Only
Current AC Power Setting Index: 0x00000001
Current DC Power Setting Index: 0x00000001
Say I want to extract the AC value for Allow hybrid sleep
, which in this case is 0x00000001
. I have the setting_guid
available to be interposed into the query string.
For now I am using this piece of code to dynamically extract the value of a specific setting:
$block = powercfg /q #{scheme_guid} #{sub_guid}
$setting = $block | Select-String -Pattern #{setting_guid} -Context 0, 8 | %{$_.Context.PostContext}
$line = $setting | Select-String -Pattern 'Current #{ac_or_dc} Power Setting Index'
$line -match 'Current #{ac_or_dc} Power Setting Index: (?<value>0x.{8})'
Write-Output ([int]$matches['value'])
This works fine for now, but the hardcoded -Context 0, 8
is not really desirable, because sometimes blocks can be really short or long and my query will fail to extract the value or it will retrieve from a wrong line.
I hope to find a cleaner way to do this, preferably programmatic and human-readable (regex is fine as long as it makes sense).
If we wish to do this task with a regular expression, we might want to start with an expression that passes newlines, similar to these:
Allow hybrid sleep[\s\S]+?Current DC Power Setting Index:\s+(.+)\s
Allow hybrid sleep[\s\S]+?Current DC Power Setting Index:\s+(.+)
Allow hybrid sleep[\w\W]+?Current DC Power Setting Index:\s+(.+)\s
Allow hybrid sleep[\d\D]+?Current DC Power Setting Index:\s+(.+)
which our desired output would be in this capturing group: (.+)
.
If this expression wasn't desired and you wish to modify it, please visit this link at regex101.com.
jex.im visualizes regular expressions:
How about this way...
$PowerData = @'
Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)
GUID Alias: SCHEME_BALANCED
Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20 (Sleep)
GUID Alias: SUB_SLEEP
Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da (Sleep after)
GUID Alias: STANDBYIDLE
Minimum Possible Setting: 0x00000000
Maximum Possible Setting: 0xffffffff
Possible Settings increment: 0x00000001
Possible Settings units: Seconds
Current AC Power Setting Index: 0x00000708
Current DC Power Setting Index: 0x00000384
Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e (Allow hybrid sleep)
GUID Alias: HYBRIDSLEEP
Possible Setting Index: 000
Possible Setting Friendly Name: Off
Possible Setting Index: 001
Possible Setting Friendly Name: On
Current AC Power Setting Index: 0x00000001
Current DC Power Setting Index: 0x00000001
Power Setting GUID: 9d7815a6-7ee4-497e-8888-515a05f02364 (Hibernate after)
GUID Alias: HIBERNATEIDLE
Minimum Possible Setting: 0x00000000
Maximum Possible Setting: 0xffffffff
Possible Settings increment: 0x00000001
Possible Settings units: Seconds
Current AC Power Setting Index: 0x00002a30
Current DC Power Setting Index: 0x00002a30
Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d (Allow wake timers)
GUID Alias: RTCWAKE
Possible Setting Index: 000
Possible Setting Friendly Name: Disable
Possible Setting Index: 001
Possible Setting Friendly Name: Enable
Possible Setting Index: 002
Possible Setting Friendly Name: Important Wake Timers Only
Current AC Power Setting Index: 0x00000001
Current DC Power Setting Index: 0x00000001
'@
[regex]::Matches($PowerData,'(?s)hybrid.*?DC').Value |
ForEach {[regex]::Matches($PSitem,'Current AC Power Setting Index.*').Value}
# Results
Current AC Power Setting Index: 0x00000001
Or
Clear-Host; (((Get-Content -Path '.\PowerDataTemplate.txt')) -match 'hybrid|AC')#[3]
<#
Current AC Power Setting Index: 0x00000708
Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e (Allow hybrid sleep)
GUID Alias: HYBRIDSLEEP
Current AC Power Setting Index: 0x00000001
Current AC Power Setting Index: 0x00002a30
Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d (Allow wake timers)
Current AC Power Setting Index: 0x00000001
#>
Clear-Host; (((Get-Content -Path '.\PowerDataTemplate.txt')) -match 'hybrid|AC')[3]
# Current AC Power Setting Index: 0x00000001
Clear-Host; [regex]::matches($(Get-Content -Path 'variable:\PowerData'),'.*hybrid.*|.*AC.*').Value
<#
Current AC Power Setting Index: 0x00000708
Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e (Allow hybrid sleep)
Current AC Power Setting Index: 0x00000001
Current AC Power Setting Index: 0x00002a30
Current AC Power Setting Index: 0x00000001
#>
Clear-Host; [regex]::matches($(Get-Content -Path 'variable:\PowerData'),'.*hybrid.*|.*AC.*').Value[2]
# Current AC Power Setting Index: 0x00000001
Or in PowerShellv5x, you can use the ConvertFrom-String or ConvertFrom-StringData cmdlets using string conversion templates.
Update for OP
I though about this a bit more, and if all you are after is a particular settings, then why not directly ask for it. For Example.
# Get only (Allow hybrid sleep)
powercfg.exe query SCHEME_MIN SUB_SLEEP HYBRIDSLEEP
# Get only the AC setting
(powercfg.exe query SCHEME_MIN SUB_SLEEP HYBRIDSLEEP) -match 'Current AC Power Setting Index'
# Results
Current AC Power Setting Index: 0x00000000
User contributions licensed under CC BY-SA 3.0