Trevor Sullivan's Tech Room

Minding the gap between administration and development

PowerShell: WMI Eventing: Monitor CPU Speed

Posted by Trevor Sullivan on 2011/01/17


Introduction

I haven’t written any articles in a while, and the last major stuff I had been working with involved permanent WMI event subscriptions. I’ve been itching to write an article like this for a while now, but just had never gotten around to it. The purpose of this article is to describe how to use PowerShell with WMI eventing to monitor changes in CPU speed. Unlike early generation CPUs, modern CPUs have embedded technology that can dynamically change the processor’s clock speed dependent on load (eg. Intel SpeedStep or AMD’s Cool ‘n Quiet).

WMI Events

Thankfully, the Windows Management Instrumentation (WMI) service, built into Microsoft Windows, offers information about CPU speed, as well as For some background on temporary WMI event subscriptions with PowerShell, check out my article on WMI events. If you’re interested in permanent event subscriptions, that don’t depend on PowerShell running in the background, check out the PowerShell PowerEvents module.

Temporary: Monitoring CPU Speed

Using a temporary event subscription, we can easily monitor CPU speed by running the following PowerShell command:

Register-WmiEvent –Query "select * from __InstanceModificationEvent within 2 where TargetInstance ISA 'Win32_Processor' and TargetInstance.CurrentClockSpeed <> PreviousInstance.CurrentClockSpeed" –Action { Write-Host "Clock speed changed" }

This will simply echo the text “Clock speed changed,” at each occurrence, to the PowerShell console. If you want to do something more fancy, you can dynamically retrieve the new clock speed from the event object in the Action block.

Register-WmiEvent –Query "select * from __InstanceModificationEvent within 2 where TargetInstance ISA 'Win32_Processor' and TargetInstance.CurrentClockSpeed <> PreviousInstance.CurrentClockSpeed" –Action { Write-Host ("Clock speed changed to: " + $Event.SourceEventArgs.NewEvent.TargetInstance.CurrentClockSpeed + "Mhz") }

image

To make things even more dynamic, we can set up a PowerShell function to respond to our event, and then call that function in the event handler. By doing this, we now allow ourselves the flexibility of redefining the event handler function, without having to delete and re-create the event registration.

function ClockSpeedChanged($tEvent)
{
    Write-Host $tEvent.SourceEventArgs.NewEvent.TargetInstance.CurrentClockSpeed
}

Register-WmiEvent –Query "select * from __InstanceModificationEvent within 2 where TargetInstance ISA 'Win32_Processor' and TargetInstance.CurrentClockSpeed <> PreviousInstance.CurrentClockSpeed" –Action { ClockSpeedChanged $Event }

Permanent: Monitoring CPU Speed

So, now we’ve looked at how to create a temporary event registration to monitor CPU speed, but this depends on having PowerShell.exe running all the time. What if we wanted to perform some action in response to the CPU speed changing, but not have to worry about invoking, and leaving, a PowerShell session? This is where the power of WMI permanent event subscriptions comes into play. The PowerEvents module for PowerShell makes these quite easy to work with.

To recap on permanent event consumers, you need to create three objects:

  1. A filter that defines the events you’re catching / responding to
  2. A consumer which defines the action that will be taken in response to event instances
  3. A binding which binds a filter to a consumer, and enables the flow of events

First, we need to create a filter object. Filters in WMI are simply objects that define which events you want to capture and respond to. The actually action of responding is handled by a different object, called a consumer. Here’s what our filter would look like:

$Filter = New-WmiEventFilter –Name CPUClockSpeedChanged –Query "select * from __InstanceModificationEvent within 2 where TargetInstance ISA 'Win32_Processor' and TargetInstance.CurrentClockSpeed <> PreviousInstance.CurrentClockSpeed"

Next, we need to create a WMI event consumer. The consumer’s purpose is to respond to the events defined in our filter. Let’s say in this case, that we want to simply log the clock speed change to a text file:

$Consumer = New-WmiEventConsumer -Name CPUClockSpeedChanged -ConsumerType LogFile -FileName c:\temp\ClockSpeed.log -Text "Clock speed on %TargetInstance.SocketDesignation% changed to: %TargetInstance.CurrentClockSpeed%" 

Note: For the above example, make sure that the folder c:\temp exists, otherwise it will not be created. The consumer will only create the text file, if it does not exist.

Finally, we create a binding between the filter and the consumer:

New-WmiFilterToConsumerBinding -Filter $Filter -Consumer $Consumer

And that’s all there is to it! Now you should start seeing events get logged to c:\temp\ClockSpeed.log when your processor’s speed changes. If you’re on a laptop, try unplugging your AC adapter to invoke a speed change. If you’re on a desktop computer, try putting it under load by starting a bunch of programs, and then letting it settle. Assuming that you’ve not disabled power saving features in your BIOS, you should see the clock speeds changing, and getting logged.

image

Advertisements

4 Responses to “PowerShell: WMI Eventing: Monitor CPU Speed”

  1. stej said

    PowerEvents are great. Immediatelly after I saw how to register handler to the WMI event, I was wondering how to unregister?

    • Trevor Sullivan said

      Hello,

      Thanks for your feedback! The documentation contains a section called “Removing Event Registrations Manually”. Let me know if you need a current copy of the documentation, and I will e-mail it to you.

      My e-mail address is pcgeek86@gmail.com.

      Cheers,
      Trevor Sullivan

      • stej said

        Trevor, thanks for your reply. I noticed your new post about unregisterig, so I’ll read it. I think I’ll find the answer there 🙂 Thx a lot.

  2. Ravi said

    Great post Trevor. One feedback I have is to wrap the PowerShell code snippets in the post. I tried IE, Chrome, and firefox. At my screen resolution, 1280×800, I don’t see the complete snippet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: