Managing Services the PowerShell way – Part 9: Eventing

We are almost finished on our journey to manage services with PowerShell. In this article I thought it might be helpful to determine when something changes in a service such as if it starts or stops. We can accomplish this in PowerShell with a concept called eventing. Windows is based on this idea of events. When something happens, an “event” occurs. We can tell PowerShell to watch for certain kinds of events and do something when they occur.

Jeffery HicksMVP By Jeffery Hicks - Tue, February 26, 2013 - 0 comments google+ icon

Jeffery Hicks is a Microsoft MVP in Windows PowerShell, Microsoft Certified Trainer and an IT veteran with 20 years of experience. Follow his blog.

Articles in this series

PowerShell and Services

Now, before we get too far into this I want to point out that I’m not a big fan of using PowerShell scripts to monitor events on a long-term basis. If you really need to know when a critical service has stopped, you need to invest in appropriate management software. PowerShell, and what I’m going to demonstrate, is great for short-term, ad-hoc monitoring such as when troubleshooting a problem.

Using WMI Events

The first technique is to use WMI. In much the same way you subscribe to an RSS feed to be notified when there is something new, we do the same thing. We set up a subscription in WMI to a particular type of event. The event is formulated by a query. In this case the class is one of several system classes related to events.

  • __InstanceOperationEvent
  • __InstanceCreationEvent
  • __InstanceModificationEvent
  • __InstanceDeletionEvent

For a service, we’re primarily interested in modification events. That is, anything that modifies the service. We start with a query like this:

Without getting too deep into the mechanics, suffice it to say there is a performance price for this type of query. When the query is running PowerShell will check WMI constantly to see if something has changed. That is very resource intensive, especially when querying a remote computer. Instead, we can tell PowerShell to only check, or poll, within a certain time frame, say every 10 seconds.

Because this is a system class, the query right now would fire events for everything in WMI that is changing. We need to limit the query further. Here we can use a special property called TargetInstance and ISA operator, to tell WMI only watch for instances that are of a specific class.

But, we want to narrow this down to a single service. When the event fires, the TargetInstance object will be written to the pipeline, which will be a service object. This means we can filter on service object properties.

I will save this to a variable, $query. Next this query needs to be registered with WMI to create the event subscription. As luck would have it there is a cmdlet called Register-WMIEvent.

When the query is registered, whenever the event is detected, in this case when the BITS service stops, PowerShell will record the event. For right now let’s register this for the local computer and not do anything but display a message.

The cmdlet won’t write anything to the pipeline, so use Get-EventSubscriber to see the subscription.

This subscription will only last for as long as this PowerShell session is running. How can you tell when an event has fired? Use the Get-Event cmdlet.

So nothing yet. I’ll stop the BITS service and wait about 10 seconds to see what happens. Well, nothing interactively. There’s no popup or anything like that. But checking the event queue again shows an event.

This is a pretty rich object. If I restart the service and it stops again, I’ll get another event. Or if I have multiple subscriptions running, all the events will share the same queue. This is where the SourceIdentifier comes in handy.

I have to drill down a bit, but I can get to not only the target instance object, but the previous instance.

With this type of subscription you have to monitor the event queue. But you can also create a more active subscription.

Responding to Events

I’m going to revise my query to check for any service that changes.

When the service changes its state, say from running to stopped, I want to log the change to a text file. I’ll create a scriptblock with the PowerShell commands I want to execute when a matching event fires.

$Event is an automatic variable for the event object that we looked at earlier. If the state of the previous and target instance is different, then the change is logged. I register this action with Register-WmiEvent.

Now when a service starts or stops, the text file is update. However, the event queue won’t show anything when you use Get-Event. If you use an action, Get-Event won’t show anything.

If you would like something more interactive, here’s a sample using the PopUp method from the Wscript.Shell COM Object.

But now look what I get:

Service Events

Service Events

The message box will automatically close in 15 seconds.

Cleaning Up

At some point you will want to clean up. Everything goes away if you close your PowerShell session. Otherwise you can remove the event subscription.

This will remove all subscriptions. Or you can specify an identifier. To clear the event queue, run this:

Summary

These techniques should work for both PowerShell 2.0 and 3.0. And let me re-iterate that I think they are best used for ad-hoc or temporary monitoring. Be sure to read full cmdlet help and examples for everything I’ve demonstrated and try this out in a non-production environment.

The next post in this series will describe how to query events using CIM.

Series NavigationManaging Services the PowerShell way – Part 8: Service accounts - Managing Services the PowerShell way – Part 10: Event queries with CIM

-1+1 (+1 rating, 1 votes)
Loading ... Loading ...
Your question wasn't answered? Ask in the new 4sysops forum!
===Leave a Comment===

Login

Lost your password?