22.07.2019»»понедельник

Check Power Scheme Powershell

22.07.2019
    65 - Comments

Summary: Use Windows PowerShell to retrieve the power plan settings for your computer. The Microsoft Scripting Guys show you how.

  1. Check Powershell Version
  2. Powershell Check File Size
  3. Check Power Scheme Powershell Download

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

The Windows PowerShell console provides an easy-to-use environment for creating and running PowerShell commands as well as generating script files that you can run at a later time. The more you work in that environment, the more likely you'll want to customize the console to meet your individual development style. For example, you might want to expand the buffer size or change the font.

Hello 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-Classwin32_powerplan-Namespacerootcimv2power`
-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:

  1. WMI query

  2. Regular expression to parse the GUID

  3. 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:

PSC:>Get-WmiObject-Classwin32_powerplan-Namespacerootcimv2power
-Filter “is Active=’true'”

__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 :rootcimv2power
__PATH:MRED1rootcimv2power:Win32_PowerPlan.InstanceID=“Microsoft:P
owerPlan{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}”
Caption:
ChangeableType :
ConfigurationName :
Description :
ElementName:MyCustomPlan1
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.

What

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:

PSC:>(Get-WmiObject-Classwin32_powerplan-Namespacerootcimv2power-Filter “is
Active=’true'”
).InstanceID
Microsoft:PowerPlan{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
PSC:>powercfg-list

PSC:>

ExistingPowerSchemes(*Active)
———————————–
PowerSchemeGUID:1bef50e5-557d-4b3b-9b29-cdde74fcfd30(MyCustomPlan1)*
PowerSchemeGUID:381b4222-f694-41f0-9685-ff5bb260df2e(Balanced)
PowerSchemeGUID:8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c(Highperformance)
PowerSchemeGUID:a1841308-3541-4fab-bc81-f71556f20b4a(Powersaver)

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:

PSC:>$guid=(Get-WmiObject-Classwin32_powerplan-Namespacerootcimv2power `
-Filter “isActive=’true'”).InstanceID.tostring()
PSC:>$guid.IndexOf(“{“)
20
PSC:>$guid.IndexOf(“}”)
57
PSC:>$guid.Substring(21,36)
1bef50e5-557d-4b3b-9b29-cdde74fcfd30

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).

PSC:> “1bef50e5-557d-4b3b-9b29-cdde74fcfd30” measure-Character
LinesWordsCharactersProperty
—–—–———-——–
36

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:

PSC:>$guid
Microsoft:PowerPlan{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
PSC:>

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:

IsPublicIsSerialNameBaseType
——–——–—-——–
TrueTrueRegexSystem.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:

PSC:>$regex.Match($guid)gm
TypeName:System.Text.RegularExpressions.Match

NameMemberTypeDefinition
—-———-———-

EqualsMethodboolEquals(System.Objectobj)

GetHashCodeMethodintGetHashCode()

GetTypeMethodtypeGetType()

NextMatchMethodSystem.Text.RegularExpressions.MatchNextMatch()

ResultMethodstringResult(stringreplacement)

ToString MethodstringToString()

CapturesPropertySystem.Text.RegularExpressions.CaptureCollectionCaptures

Groups PropertySystem.Text.RegularExpressions.GroupCollectionGroups{get;}

Index PropertySystem.Int32Index{get;}

LengthPropertySystem.Int32Length{get;}

Success
PropertySystem.BooleanSuccess{get;}

ValuePropertySystem.StringValue{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:

PSC:>$guid=(Get-WmiObject-Classwin32_powerplan-Namespacerootcimv2power`
-Filter “isActive=’true'”).InstanceID.tostring()
PSC:>$regex=[regex]“{(.*?)}$”
PSC:>$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:

PSC:>$regex=[regex]“{.*}$”
PSC:>$regex.Match($guid)

PSC:>

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:

PSC:>$guid=(Get-WmiObject-Classwin32_powerplan-Namespacerootcimv2power-Fi
lter “isActive=’true'”).InstanceID.tostring()
PSC:>$regex=[regex]“{(.*?)}$”
PSC:>$regex.Match($guid)
Success:True
Captures:{1bef50e5-557d-4b3b-9b29-cdde74fcfd30}
Index:21
Length:36
Value :1bef50e5-557d-4b3b-9b29-cdde74fcfd30
PSC:>$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}

PSC:>$regex.Match($guid).groups[1].value
1bef50e5-557d-4b3b-9b29-cdde74fcfd30
PSC:>

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

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell and WMI or CIM cmdlets to view and to set power plans on his laptop.

Microsoft Scripting Guy, Ed Wilson, is here.

Tomorrow, the Scripting Wife and I are at the Microsoft Technology User Group in Oslo, Norway. I will be talking about using Windows PowerShell 3.0 to manage a remote Windows 8 workstation. Last night we were in Stockholm with the Stockholm PowerShell User Group, and today is a travel day.

We are taking the beautiful train from Stockholm to Oslo. In addition to being a great way to travel, it provides stunning views, and a comfortable compartment within which to write Hey, Scripting Guy! Blog posts.

All these trains, user group presentations, and more trains, got me to thinking: I like to have my laptop running full power when making a user group presentation—of course, I am always plugged in to power while doing so. When I am on a train, or in a plane, I generally am running on battery (although most of the trains we have been riding on also have power at the seat). So, when plugged into electricity, I want to run the laptop on full power; when running on battery, I want to run the laptop on maximum conserve power. I think this calls for a quick Windows PowerShell script. But first, I need to spend a bit of time talking about WMI, CIM, and the Win32_PowerPlan WMI class.

Windows 7 introduced the Win32_PowerPlan WMI class. This WMI class resides in the RootCimv2Power WMI namespace. Because this is not the default RootCimv2 namespace, this means that any script or code to query from this class must include the RootCimv2Power namespace in the code. To enumerate the available power plans on the laptop, I can use either Get-WmiObject, or, in Windows PowerShell 3.0, I can use the Get-CIMInstance class. Either one works and using one as opposed to the other, in this case, is a simple matter of substituting one name for the other. The Get-WmiObject command is shown here, where gwmi is an alias for the Get-WmiObject cmdlet, -NS is a parameter alias for –NameSpace, select is an alias for the Select-Object cmdlet, ft is an alias for the Format-Table cmdlet, and –a is a partial parameter for –autosize.

gwmi -NS rootcimv2power -Class win32_PowerPlan select ElementName, IsActive ft -a

ElementName IsActive

———– ——–

Balanced False

Check Power Scheme Powershell

High performance True

Power saver False

Check Powershell Version

An expanded version of the command is show here. This is still a single-line command with complete cmdlet names and parameter names. I have broken it at the pipe character for readability:

Get-WmiObject -Namespace rootcimv2power -Class win32_PowerPlan

Select-Object -Property ElementName, IsActive

Format-Table -Property * -AutoSize

If I do a direct substitution, from the short form of the command to Get-CimInstance, an error arises when I run the code. This is because Get-CimInstance does not have a parameter alias NS for the NameSpace parameter (by the way, Get-CimInstance uses –classname instead of –class for the complete parameter name as well). The error is shown here.

The easy solution: Just use –N instead of the parameter alias –NS. This technique is shown here.

PS C:> Get-CimInstance -N rootcimv2power -Class win32_PowerPlan select ElementNa

me, IsActive ft -a

ElementName IsActive

———– ——–

Balanced False

High performance True

Power saver False

Making a particular power plan active

To make a particular power plan active, I only need to call the Activatemethod from a specific instance on a Win32_PowerPlan WMI class. What this means is that I return a specific power plan via the Win32_PowerPlan WMI class, and then call the Activatemethod. This is really easy by using the Get-WmiObject cmdlet—it is a bit more difficult by using the CIM classes.

Note The new way to work with WMI classes is to use the new CIM interface. The OLD WMI COM interface is now legacy. This means that you should begin learning the new CIM cmdlets, and, as far as possible, use them instead of the legacy methods. The CIM cmdlets are much more powerful, and once mastered, they are actually easier to use and to understand. For a good overview of the CIM cmdlets see this article.

I will illustrate each technique in the following sections.

Using Get-WmiObject

First, by using the Get-WmiObject cmdlet, I add a filter that returns only one power plan. In this case, I want to return only the Power Saver power plan. I store the returned object in a $p variable. Once I have done this, I call the Activatemethod, as shown here.

$p = gwmi -NS rootcimv2power -Class win32_PowerPlan -Filter “ElementName =’Power Saver'”

$p.Activate()

I can certainly use the following query to confirm that the change worked, but it is obvious when the laptop screen dramatically dims. J

Powershell Check File Size

gwmi -NS rootcimv2power -Class win32_PowerPlan -Filter “IsActive = ‘true'”

If I am in doubt, I can also verify in the Power Options dialog box, as shown here.

Using the CIM cmdlets to set the power plan on my laptop

The procedure to set the power plan on my laptop is exactly the same whether I use the CIM cmdlets or whether I use the Get-WmiObject cmdlet—I must return an instance of the power plan, and I must make it active.

However, the CIM cmdlets do not permit calling methods from “de-serialized” or “non-live” objects. It is not a good idea and can actually lead to potential instability. The old WMI COM interface does permit this calling of methods from the non-live objects. When I use Get-WMiObject and return a list of processes (via Win32_Process), the process objects are no longer live. In fact, I could stop processes, or start new processes, and the changes are not represented in the variable containing the returned process objects.

This is something people often forget. If I then take one of these offline processes and attempt to terminate the process, and the process no longer exists, then an error arises. By using CIM, this problem never happens because I cannot call methods on the returned objects. Instead, I must use the Invoke-CimMethod cmdlet. The cmdlet is easy to use, and I will follow the same procedure I used with Get-WmiObject.

$p = Get-CimInstance -Name rootcimv2power -Class win32_PowerPlan -Filter “ElementName = ‘High Performance'”

Invoke-CimMethod -InputObject $p -MethodName Activate

Note One thing I should mention is that the new CIM interface is AMAZINGLY FAST! Whereas the call using Get-WmiObject took nearly 10 seconds to return, the Invoke-CimMethod call returned immediately.

Join me tomorrow when I will write the actual script that will set the appropriate power plan for my laptop.

Check Power Scheme Powershell Download

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy