Use PowerShell and WMI or CIM to View and to Set Power Plans

Use PowerShell and WMI or CIM to View and to Set Power Plans

  • Comments 5
  • Likes

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.

Image of command output

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 Activate method 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 Activate method. 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 Activate method, 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.

Image of Power Options dialog box

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

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Love u Script Guy!

  • Hi Ed,

    I hope your trip is still continuing smoothly and that every connection worked so far!

    ( btw: I'm just wondering that you were in Stockholm last night ... )

    The CIM Cmdlets are really interesting and worth spending some time on learning how to use them!

    But what I couldn't verify here is that the "Get-WmiObject" is much slower than the "Invoke-CimMethod"),

    at least this is not true for my desktop PC. I did 10 loops to switch between 'balanced' and 'energy saver' mode.

    The results are the same ... maybe that it behaves different for a laptop computer, but the time it takes to call each "Activate" method is not too different.

    PS Z:\> (Measure-Command {

    1..10| %{

    (gwmi -NS root\cimv2\power -Class win32_PowerPlan -Filter "ElementName ='Ausbalanciert'").Activate()

    (gwmi -NS root\cimv2\power -Class win32_PowerPlan -Filter "ElementName ='Energiesparmodus'").Activate()

    }}).TotalSeconds

    0,9452381

    PS Z:\> (Measure-Command {

    1..10| %{

    Get-CimInstance -N root\cimv2\power -Class win32_PowerPlan -Filter "ElementName ='Ausbalanciert'" | Invoke-CimMethod -MethodName Activate > $null

    Get-CimInstance -N root\cimv2\power -Class win32_PowerPlan -Filter "ElementName ='Energiesparmodus'" | Invoke-CimMethod -MethodName Activate > $null

    }}).TotalSeconds

    0,9446345

    Have a nice time, greetings to Teresa of course!

    Klaus.

  • @Serhad MAKBULOGLU thanks.

    @K_Schulte -- yes the trip is going well, and all connections are working. Visiting CERN today was awesome. We just arrived in Zurich and are going to the Microsoft office tomorrow to visit friends and mentors. Where I have found Get-WMIObject to be much slower, was not running locally, but when working with remote machines. Once I have a CIM connection, it is very fast to make repetitive queries.

  • Hi Ed,

    as I'm always interested in runtime comparisons, I did some measurements against a networked remote machine and whatever machine, I used, Get-WmiObject was faster than Get-CimMethod here!

    I ran the timings from a Win7 64bit client machine using the Powershell-ISE x64.

    The target machines were running on WIN2008R2 (x64) server OS.

    The timings were done like this:

    $p1=Get-CimInstance -N root\cimv2\power -ComputerName win2008r2_server -Class win32_PowerPlan -Filter "ElementName ='Ausbalanciert'"

    $p2=Get-CimInstance -N root\cimv2\power -ComputerName win2008r2_server -Class win32_PowerPlan -Filter "ElementName ='Energiesparmodus'"

    $t_cim=(Measure-Command {

    1..50| %{

       Invoke-CimMethod -inputobject $p1 -MethodName Activate

       Invoke-CimMethod -inputobject $p2 -MethodName Activate

    }}).TotalSeconds

    $p1=gwmi -NS root\cimv2\power -ComputerName win2008r2_server -Class win32_PowerPlan -Filter "ElementName ='Ausbalanciert'"

    $p2=gwmi -NS root\cimv2\power -ComputerName win2008r2_server -Class win32_PowerPlan -Filter "ElementName ='Energiesparmodus'"

    $t_gwmi=(Measure-Command {

    1..50| %{

       $p1.Activate()

       $p2.Activate()

    }}).TotalSeconds

    "Time used for 100 calls of 'Invoke-CimMethod': " + $t_cim

    "Time used for 100 calls of 'Get-WmiObject'   : " + $t_gwmi

    --- The results are:

    Time used for 100 calls of 'Invoke-CimMethod': 5.3876405

    Time used for 100 calls of 'Get-WmiObject'   : 3.9447496

    ... and I wonder why ...

    Have a nice day

    Klaus.

  • @K_Schulte interesting ... it will give me something to look at when I return home.