Summary: Use Windows PowerShell to retrieve the power plan settings for your computer. The Microsoft Scripting Guys show you how.
Hey, Scripting Guy! I need to have a way to easily retrieve the power plan settings for the active power plan on my computer. I would like to have an easy to read display of the setting name, the allowable values, and the current value for when the computer is on battery power and for when it is on AC power. I know this seems like a lot to ask, but can Windows PowerShell retrieve this information for me?
— LC
Microsoft Scripting Guy Ed Wilson here. Today is Friday; at least it is if you live in Charlotte, North Carolina, and you are a Scripting Guy who is working on next week’s Hey, Scripting Guy! Blog posts. Better than the fact that it is Friday, it is actually Friday afternoon and as soon as this article is completed, I plan on securing for the day. Not that I will turn off my computer, or even that I will log out of the Redmond domain at work, but my writing mode will shut down and my play mode will kick in. I have a really complex WMI script I have been knocking around for the last two days, and I want to dig into it and figure out why it is not providing me the information I desire. As far as I can tell, no one has ever written a WMI script to do what I am working on, including the product group that wrote the WMI class I am messing around with. I did get a 1,500-line VBScript from one of the test engineers to exercise the class, but dude! I was hoping for something a bit clearer. I am going to fire up the WMI administrative tools, and dig into the various class associations to see if I can figure out the relationships. I am really looking forward to it.
Anyway, LC, I figure you are not interested in a 1,500-line VBScript, or even a 200-line Windows PowerShell script. So here you go–four lines of code. Admittedly, some it is a bit compact, but I will spend the next 2,000 words explaining it. The complete Get-ActivePowerPlanSettingsPwrCfg.ps1 script is shown here.
Get-ActivePowerPlanSettingsPwrCfg.ps1
$plan = Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power `
-Filter “isActive=’true'”
$regex = [regex]“{(.*?)}$”
$planGuid = $regex.Match($plan.instanceID.Tostring()).groups[1].value
powercfg -query $planGuid
I love using WMI to make command-line utilities more manageable. The PowerCfg.exe utility is a cool tool for interactively exploring and manipulating the power settings. One problem is the plethora of switches and the fact it relies on the power plan GUID for many operations. This means retrieving the GUID for the present power plan, and either copying it to the clipboard (assuming your current console has copy/paste enabled) or doing a lot of writing and typing. Or performing impressive memory feats.
In the Get-ActivePowerPlanSettingsPwrCfg.ps1 script, I basically “cheat.” I use WMI to retrieve the current power plan, use regular expressions to retrieve the GUID for the active power plan, and then pass the GUID for the active power plan to the powercfg.exe utility and tell it to retrieve the settings for the plan. There are essentially three steps:
-
WMI query
-
Regular expression to parse the GUID
-
Call to the Powercfg executable with the appropriate parameters and arguments
The Get-ActivePowerPlanSettingsPwrCfg.ps1 script consists of four logical lines (the first line, the WMI query, is broken into two lines because of limitations of displaying long lines of code on the blog platform. The backtick character (`) in Windows PowerShell is the line continuation character.
The query to the Win32_PowerPlan WMI class was discussed in yesterday’s Hey, Scripting Guy! Blog post.
The information that will be stored in the $plan variable is shown here:
PS C:\> Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power
-Filter “is Active=’true'”
PS C:\>__GENUS : 2
__CLASS : Win32_PowerPlan
__SUPERCLASS : CIM_SettingData
__DYNASTY : CIM_ManagedElement
__RELPATH : Win32_PowerPlan.InstanceID=“Microsoft:PowerPlan\\{1bef50e5-557d-
4b3b-9b29-cdde74fcfd30}”
__PROPERTY_COUNT : 7
__DERIVATION : {CIM_SettingData, CIM_ManagedElement}
__SERVER : MRED1
__NAMESPACE : root\cimv2\power
__PATH : \\MRED1\root\cimv2\power:Win32_PowerPlan.InstanceID=“Microsoft:P
owerPlan\\{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}”
Caption :
ChangeableType :
ConfigurationName :
Description :
ElementName : My Custom Plan 1
InstanceID : Microsoft:PowerPlan\{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
IsActive : True
There are only three properties that display any kind of interesting information: elementname, instanceID, and IsActive. Of those three properties, the only one we need for the Get-ActivePowerPlanSettingsPwrCfg.ps1 script is the InstanceID. Unfortunately, the InstanceID that is used by WMI is different than the GUID that is used by the PowerCfg.exe utility.
By comparing the results of a WMI Query that only returns the InstanceID with a list of power schemes retrieved by the PowerCfg utility, it becomes apparent that it is possible to manipulate the WMI data to retrieve the GUID. The output from WMI and from PowerCfg is shown here:
PS C:\> (Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power -Filter “is
Active=’true'”).InstanceID
Microsoft:PowerPlan\{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
PS C:\> powercfg -list
PS C:\>Existing Power Schemes (* Active)
———————————–
Power Scheme GUID: 1bef50e5-557d-4b3b-9b29-cdde74fcfd30 (My Custom Plan 1) *
Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)
Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance)
Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver)
It would be possible to use string manipulation to retrieve the GUID from the WMI information. By using the IndexOf method from the system.string .NET Framework class, and the substring method from the same class, the location of the “{“ and the “}” can be determined and the length of the characters determined. When the start position and the length are known, the substring method returns the GUID from the WMI InstanceID. This is shown here:
PS C:\> $guid = (Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power `
-Filter “isActive=’true'”).InstanceID.tostring()
PS C:\> $guid.IndexOf(“{“)
20
PS C:\> $guid.IndexOf(“}”)
57
PS C:\> $guid.Substring(21,36)
1bef50e5-557d-4b3b-9b29-cdde74fcfd30
PS C:\>
By the way, to figure out the length of the GUID, I did not count up the letters, numbers, and dashes. That is way too confusing. I used the Measure-Object cmdlet with the character parameter. The alias for the Measure-Object cmdlet is measure. Therefore, the command is shown here. (Windows PowerShell is smart enough to ignore the “” that are required to supply a string to the Windows PowerShell console. Therefore, the string actually has 36 characters in it. You do not have to subtract 2 from this number to use it with substring).
PS C:\> “1bef50e5-557d-4b3b-9b29-cdde74fcfd30” | measure -Character
Lines Words Characters Property
—– —– ———- ——–
36
PS C:\>
Before Windows PowerShell came along, I used Notepad to do my counting for me. Notice the cursor position indicator in the lower right corner of the following image. The number states that it is on line 1 and column 37 in Notepad; therefore, you need to always subtract one from the column number indicated because it is telling you where the first blank space resides.
The hardest part about using regular expressions is figuring out the pattern. We have several good Hey, Scripting Guy! Blog posts that talk about using regular expressions with VBScript as well as with Windows PowerShell. The VBScript regular expression articles are useful for Windows PowerShell scripters because they include information about the regular expression pattern. By the same token, the Windows PowerShell regular expression articles are of use to VBScript scripters.
The regular expression pattern that is used here is composed of eight characters that make up six different commands. The characters in the regex pattern are shown in Table 1.
Table 1
Character & meaning |
Character & meaning |
Character & meaning |
Character & meaning |
Character & meaning |
Character & meaning |
Character & meaning |
Character & meaning |
{ |
( |
. |
* |
? |
) |
} |
$ |
Literal character. Opening curly bracket. |
Groups the .*? Sub-expression. This is the opening parenthesis. |
The period indicates any character. Could be a letter, or number, a dash or underline. |
The asterisk means zero or more occurrences of the previous character. |
The question mark means do a lazy regex match (as opposed to a greedy pattern match). |
Closes the grouping for the sub-expression. |
Literal character. Closing curly bracket. |
Matches previous character only at the end of a line. Therefore, are looking for closing curly brackets that are found at end of line. |
Because there is only one active power plan, it is possible to retrieve the InstanceID directly, and then convert it to a string. In the Get-ActivePowerPlanSettingsPwrCfg.ps1 script, I did not do this. Rather, I stored the entire object in the $plan variable. But for testing from the command line, this works out well. $guid will contain the following information:
PS C:\> $guid
Microsoft:PowerPlan\{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
PS C:\>
After the InstanceID has been converted to a string and stored in the $guid variable, the regex pattern is assigned to a variable called $regex. To create our regular expression pattern, we place the pattern inside a pair of quotation marks, and use the [regex] type accelerator to “cast” the string to a regex object. You can use the gettype method to check on the type object that has been created. This is shown here:
PS C:\> $regex.gettype()
PS C:\>IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Regex System.Object
The match method from the regex object is used to perform the regular expression pattern match on the string that is supplied to the method call. The method returns a match object from the System.Text.RegularExpressions namespace. The match object has a number of methods and properties that are all listed here. GM is an alias for Get-Member and is used to show the members (methods and properties) of the match object:
PS C:\> $regex.Match($guid) | gmTypeName: System.Text.RegularExpressions.Match
Name MemberType Definition
—- ———- ———-
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
NextMatch Method System.Text.RegularExpressions.Match NextMatch()
Result Method string Result(string replacement)
ToString Method string ToString()
Captures Property System.Text.RegularExpressions.CaptureCollection Captures …
Groups Property System.Text.RegularExpressions.GroupCollection Groups {get;}
Index Property System.Int32 Index {get;}
Length Property System.Int32 Length {get;}
Success Property System.Boolean Success {get;}
Value Property System.String Value {get;}
The cool thing about Windows PowerShell is that the match object that is returned by calling the match method from the regex class automatically expands to display the values of each of the properties. This sequence of commands is shown here, and illustrates how I went from the WMI object to retrieving the GUID:
PS C:\> $guid = (Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power `
-Filter “isActive=’true'”).InstanceID.tostring()
PS C:\> $regex = [regex]“{(.*?)}$”
PS C:\> $regex.Match($guid)
Groups : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}, 1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
Success : True
Captures : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}}
Index : 20
Length : 38
Value : {1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
The last thing we need to hone in on is the fact that the Groups property actually returns two different values. The first one is the GUID with the { } that were the delimiters for the regex pattern. The curly brackets will mess up the call to powercfg, and therefore it is necessary to remove them. This is where the subexpression came into play. If the regex pattern had been “{.*?}$” without the ( ) that were used in our actual pattern, the second group would not have been created. This is shown here:
PS C:\> $regex = [regex]“{.*}$”
PS C:\> $regex.Match($guid)
PS C:\>Groups : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}}
Success : True
Captures : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}}
Index : 20
Length : 38
Value : {1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
It would therefore be necessary to come back and remove the { } from the match value. Because our regex pattern {(.*?)}$ contains the sub-expression and therefore returns the second group match, we can index into the collection of groups and choose the second group, the one without the { } surrounding the GUID. When we have the specific group, the value can be directly retrieved. This is shown here. First, I use WMI to store the InstanceID as a string in the $guid variable. Next, I create the regex pattern and call the Match method. Next, I select only the second match group, and finally I display the value of that group:
PS C:\> $guid = (Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power -Fi
lter “isActive=’true'”).InstanceID.tostring()
PS C:\> $regex = [regex]“{(.*?)}$”
PS C:\> $regex.Match($guid)
Success : True
Captures : {1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
Index : 21
Length : 36
Value : 1bef50e5-557d-4b3b-9b29-cdde74fcfd30 PS C:\> $regex.Match($guid).groups[1] Groups : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}, 1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
Success : True
Captures : {{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}}
Index : 20
Length : 38
Value : {1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
PS C:\> $regex.Match($guid).groups[1].value
1bef50e5-557d-4b3b-9b29-cdde74fcfd30
PS C:\>
The last thing that is done is to use powercfg to perform a query for the particular power plan. This is a straightforward command as is shown here:
powercfg -query $planGuid
The results from running the Get-ActivePowerPlanSettingsPwrCfg.ps1 script are shown in the following image.
LC, that is all there is to using WMI and regular expressions to retrieve the active power plan GUID. WMI Week will continue tomorrow when we continue working with WMI power classes.
We invite you to follow us on Twitter and Facebook. If you have any questions, send email to us at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys
Great post, thanks. One small correction, it seems ‘IsActive’ is the Property of Win32_PowerPlan not ‘Is Active’