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.
Detecting laptop power plans
Windows 7 introduced the Win32_PowerPlan WMI class. This WMI class resides in the Root\Cimv2\Power WMI namespace. Because this is not the default Root\Cimv2 namespace, this means that any script or code to query from this class must include the Root\Cimv2\Power 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 root\cimv2\power -Class win32_PowerPlan | select ElementName, IsActive | ft -a
ElementName IsActive
----------- --------
Balanced False
High performance True
Power saver False
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 root\cimv2\power -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 root\cimv2\power -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 root\cimv2\power -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
gwmi -NS root\cimv2\power -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 root\cimv2\power -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.
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