/build/static/layout/Breadcrumb_cap_w.png

Tools for Proactive Troubleshooting in Windows 7

Overview

When troubleshooting a problem you sometimes need to sit and wait for it to occur. Or there may be situations where you want to take a more proactive and plan a specific response should something happen like a mission critical service stopping or a specific process starting. In this article, I'll explain how to use a variety of tools in Windows 7 to watch for specific events and take action when they occur.

In a Windows environment, when something happens like the creation of a new file, a special thing happens referred to as an event. An event is a programmed response and the types of events vary depending on the operating system or application. You cannot program your own events, but you can wait for them and when they happen, you can react. When an event is triggered or fired, Windows or the application you might be using records it. Fortunately you don't have to be a Windows programmer to take advantage of events, although I will admit it does require some advanced knowledge and a little sophistication when it comes to scripted solutions. But I'll guide you as much as I can and leave you with some working examples to get you started.

I'll focus on some common events that you might want to catch such as a service stopping, a process starting and a file getting created.

Using the Task Scheduler

The first tool we have at our disposal is the task scheduler in Windows 7. Depending on the event you are waiting for and what action you wish to take this is a relatively simple monitoring solution. Often, when an event fires, something is written to an event log. With the task scheduler we can create a task that is triggered when the specific event is recorded. Naturally, you will need to know a few specific such as an event ID, source and log. The first thing we need to do is create a new task. You will need to create this task on the computer you want to monitor; unless you have configured event forwarding which is a topic for another day.

I suggest that you create a folder for your tasks in the Task Scheduler. Windows 7 has many scheduled tasks and it will make your life much easier. Right-Click on Task Scheduler Library in the tree pane and select New Folder. Select the folder. In the left pane, click on Create Basic task and enter a name for your task.


Figure 1

Click Next. Select the 'When a specific event is logged' option.


Figure 2

Now you will be prompted to select the event log information. Be as specific as you can. In my example I'm going to select the System event log, using Service Control Manager as the source and filtering on event id 7036.


Figure 3

The next screen is where it gets interesting. This is where you decide what you want to do when the event fires. You can start a program or script, send an email or display an interactive popup message. It is possible to create advanced tasks that will do several of these items but for now I'm just going to display a message.


Figure 4

In the next screen I'll define the message title and text.


Figure 5

The last step is merely a review, although I also have the option to open advanced properties if I want to tweak anything.


Figure 6

At the point the task is enabled. If I manually stop the Spooler service, an event is written to the log which triggers the scheduled task which displays the popup message.


Figure 7

Unfortunately, I will also get the message for any service that stops. In this particular situation I need a way to get more detailed information. If the event you are monitoring can be uniquely identified then you shouldn't need to take any other steps. But in my scenario I need to refine my task so that it only responds when the Spooler service stops. This is a little more complicated and requires a little XML knowledge.

I can either create a new advanced task or edit my existing task by opening its properties. Select the Triggers tab and edit the selected trigger. Choose Custom.


Figure 8

Click on New Event Filter. Click on XML and check the box to manually enter XML. I'm going to copy and paste this XML code into the window.


' 
''' 
' 

I don't have the space to explain how I developed this suffice it to say that I looked at the raw XML of an event in the Event Viewer. You should be able to download this code from here.


Figure 9

Click OK a few times and the change is immediate. Now the only time I get the popup is when the Spooler service stops.

Using WBEMTest

Unfortunately not every type of event you might want to monitor ends up in the event log. The other approach is to use WMI and create listeners for events. One tool you can use is WBEMTest.exe which has been available on all versions of Windows since XP. Let's look at setting up an event monitor to watch when a process starts on a computer. For the sake of this article we'll watch for new instances of CALC.EXE.

One drawback to WBEMTest is that you can't automatically execute a program or script. All you get is a notification. But this is still an excellent tool to make sure you query works. After that you can use it in either VBScript or PowerShell. I'll cover an approach using the latter in a little bit.

To get started we first need to connect to WMI on a computer. Click Start-Run and enter wbemtest.


Figure10

Click the Connect button. If you want to connect to the local computer, make sure the namespace says root\cimv2 and click Connect. If you want to connect to a remote computer, modify the namespace so that it is \\computername\root\cimv2.


Figure11

Optionally, you can enter alternate credentials for a remote computer in the format domain\username. You can leave everything else. If all goes well you should see something like Figure 12.


Figure 12

In WMI-speak, we will be creating a notification query. This type of query creates a listener that monitors WMI and when a matching event is detected, a notification is sent to the listener. The notification query is structured similarly to regular WMI queries. A typically notification query looks like this.

Select * from' Within' Where TargetInstance ISA

The event is system class. These are the common event classes:

__InstanceCreationEvent

__InstanceModificationEvent

__InstanceDeletionEvent

Be aware that the name has a double underbar leading it.

The second part of the query is the polling interval. This is how often WMI will check to see if the event occurred. This should be short enough to be useful but not so short that WMI has a constant connection. I find an interval of 5 seconds is often more than adequate. So our query thus far should look like:

Select * from __InstanceCreationEvent within 5

However this would fire for any new object written to WMI. We want to limit the query to a Win32_Process. Using a Where clause we configure the query to check the TargetInstance, the object that is created and only those that are process objects.

Select * from __InstanceCreationEvent within 5 where TargetInstance ISA 'Win32_Process'

Almost there. This version will fire when ANY new process is created, any maybe you want that. But I want to limit my query to only processes where the name is CALC.EXE. I'll modify my query using the And operator. This is my final query.

Select * from __InstanceCreationEvent within 5 where TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='calc.exe'

In WBEMTest.exe I click the Notification Query button and paste in this text.


Figure 13

When I click Apply, a new window pops up waiting for an event to happen that matches my query. If I start Notepad, nothing happens. But when I start Windows Calculator, within 5 seconds I will get a result in the query window.


Figure 14

I can double click the entry to examine the WMI process object. I tend to check the box to hide system properties.


Figure 15

Double click on Target Instance. Then in the next property window click View Embedded. This will display all the properties of the process.


Figure 16

As long as you leave the query window open you'll get notifications whenever a new process starts. But as soon as you close the window, the monitoring stops. Using WBEMTest is a handy way for general event monitoring, but there is no provision for taking action. However, once you have figured out a notification query that works, you can leverage VBScript or Windows PowerShell. Based on experience I can tell you that using the former is very complicated so we'll focus on using the latter.

Using PowerShell

The advantage of using a management and automation tool like PowerShell is that you have tremendous flexibility on what action you wish to take when an event has been detected. PowerShell2.0 offers two cmdlets for managing and listening for events.

Register-WMIEvent

If you have a WMI notification query working in WBEMTest, you can use that same query in PowerShell with the Register-WMIEvent cmdlet. Let's return to our original scenario where we want to take action when the Spooler service stops. Using WBEMTest I've worked out a notification query.

Select * from __InstanceModificationEvent within 10 where targetinstance isa 'Win32_Service' AND TargetInstance.Name='spooler' AND TargetInstance.State='Stopped'"

The Register-WMIEvent cmdlet makes it very easy to setup an event subscription for a remote computer that is watched from my computer.

$query="Select * from __InstanceModificationEvent within 10 where targetinstance isa 'Win32_Service' AND TargetInstance.Name='spooler' AND TargetInstance.State='Stopped'"
Register-WMIEvent -Query $query -sourceIdentifier "StoppedService" -MessageData "The Spooler Service has stopped" -computername "SERVER01"

When I execute this code, PowerShell will create an event subscriber.

PS C:\> Get-EventSubscriber
SubscriptionId'' : 3
SourceObject'''' : System.Management.ManagementEventWatcher
EventName''''''' : EventArrived
SourceIdentifier : StoppedService
Action'''''''''' :
HandlerDelegate' :
SupportEvent'''' : False
ForwardEvent'''' : False

As long as my PowerShell session is open it will watch for events where the spooler service stops. When this happens the event is registered. Use the Get-Event cmdlet to check if any events have fired.

PS C:\> get-event
ComputerName'''' :
RunspaceId'''''' : 6137adf2-d8ca-4ccb-bfac-2d89f2abedcd
EventIdentifier' : 2
Sender'''''''''' : System.Management.ManagementEventWatcher
SourceEventArgs' : System.Management.EventArrivedEventArgs
SourceArgs'''''' : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : StoppedService
TimeGenerated''' : 3/17/2011 7:43:39 PM
MessageData''''' : The Spooler Service has stopped

The other way you might want to use this cmdlet is to include the 'Action parameter. This parameter takes a script block which is a PowerShell command that you want to execute, perhaps sending a message using Send-MailMessage or launching another script. The 'Action parameter will create a background job for your script block that is launched when the event fires. See cmdlet help for Register-WMIEvent for more details.

Register-ObjectEvent

PowerShell can also subscribe to events from other sources like the .NET Framework. Let's say we have a folder that we want monitor when files change. The .NET framework includes a class for exactly this type of event. We'll create this watcher class, specifying the folder to watch.

PS C:\> $watcher=[System.IO.FileSystemWatcher]("c:\work")

Next we'll use the Register-ObjectEvent cmdlet. This works very similarly to Register-WMIEvent. In my example I'm going to write information to a log file whenever a new file is created in C:\Work.

PS C:\> Register-ObjectEvent -InputObject $watcher -Eventname "Created" -SourceIdentifier "FolderChange" `
>> -MessageData "A new file was created" -Action {
>> "$(Get-Date) A new file was created: $($Event.SourceEventArgs.fullpath)"
>>| Out-File $env:temp\log.txt -append' }
>>
Id'''''' Name'''''''''' State''''' HasMoreData'''' Location'''''''' Command
--'''''' ----'''''''''' -----''''' -----------'''' --------'''''''' -------
3''''''' FolderChange'' NotStarted False'''''''''''''''''''''''''''''''' ...

The EventName parameter corresponds to the event name which in the case of the FileSystemWatcher class can be 'Created', 'Changed' or 'Deleted'.

Next, I need to enable the watcher object.

PS C:\> $watcher.EnableRaisingEvents=$True

The Get-EventSubscriber cmdlet shows me the new watcher.

PS C:\> get-eventsubscriber -SourceIdentifier FolderChange
SubscriptionId'' : 4
SourceObject'''' : System.IO.FileSystemWatcher
EventName''''''' : Created
SourceIdentifier : FolderChange
Action'''''''''' : System.Management.Automation.PSEventJob
HandlerDelegate' :
SupportEvent'''' : False
ForwardEvent'''' : False

PowerShell will now 'watch' for any new files created in C:\Work. When a new file is created a line is added to the log file with the date and full file name.

PS C:\> get-content $env:temp\log.txt
03/17/2011 20:20:49 A new file was created: C:\work\sub5.txt

While I admit this is an advanced topic, working with events in PowerShell opens up some tremendous possibilities. The biggest challenge is likely being able to define what type of event you need to watch. But once that is worked out, you can be more responsive and even pro-active. The ad hoc approach to event monitoring that I discuss is meant to be a short-term and for the most part temporary. The event subscribers stop listening as soon as you close your PowerShell session. For ongoing monitoring and alerting, you will be better served by investing in a 3rd party management solution.

Read More About It

Working with event in PowerShell is admittedly a complex task, yet it offers tremendous opportunities. If you'd like to learn more about PowerShell and events take a look at Windows PowerShell 2.0: TFM by Don Jones and Jeffery Hicks (SAPIEN Press 2010) and Windows PowerShell in Action 2nd Edition by Bruce Payette (Manning 2011).


Comments

This post is locked
 
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ