Windows PowerShell: Responding to WMI Events

Tracking, notifying and responding to system-level events is something Windows does well, but you can also do that with Windows PowerShell.

Don Jones

One of the neat things about the Windows OS is its support for events. Whenever something occurs in the OS, it generates an event. Bits of code, such as applications, can register to be notified of specific events so they can respond with some action. For example, when you click on a button in a dialog box, the application receives notification of a “click” event, and knows to do whatever it’s supposed to do when someone clicks that button.

Windows Management Instrumentation (WMI) can also produce events, and you can register Windows PowerShell v2 to receive those events. You can then use the shell to execute whatever commands you prefer in response to those events. WMI will typically raise one of a fairly small number of events, but it can do so for a huge range of different WMI classes.

There are three key points to using WMI events:

  • knowing which event you want
  • knowing the class for which you want the event
  • using the Register-WMIEvent cmdlet to register for event notifications

Simple Events

Some WMI classes generate events. For example, the Win32_ProcessStartTrace class generates events whenever a process starts. It will also do so in other situations. When the event for a new process is raised, it has a source identifier of “Process Started.” To register for events, you would run this command:

Register-WmiEvent –class "Win32_ProcessStartTrace" 
–sourceIdentifier "Process Started"

Of course, simply knowing that a process started isn’t useful. You will probably want to define some action to log the process, send an e-mail or even kill the process.

Run Get-EventSubscriber to see the event notification subscription you just created. To remove all event registrations, run Get-EventSubscriber | Unregister-Event. You can also use Unregister-Event to remove a specific subscription by ID number.

Better Events

Some of the system-level events WMI can produce are even more useful. For example, an event called __instancecreationevent is fired whenever a new instance of a WMI class is created; __instancedeletionevent fires whenever an instance is deleted. This might not seem useful, but think about it, almost every element of the OS and computer hardware is represented by some instance of a WMI class. For example, Win32_LogicalDisk will get a new instance when you attach a removable storage device. Win32_Process will lose an instance when a process quits.

Want to display a message when users insert a new USB drive?

Register-wmievent –query "select * from __instancecreationevent within 5 where targetinstance isa 'win32_logicaldisk'" –action { Write "You had better not put any proprietary information on that!" }

That query can be pretty difficult to break down, so here’s what it’s doing:

  • SELECT * FROM __instancecreationevent (that’s two underscores in the event name, by the way) simply specifies that all properties from that event should be retrieved.
  • WITHIN 5 indicates that we only want to check for events every five seconds. Don’t set this number too low or you’ll end up with a lot of computing power spent on constantly checking for updates.
  • WHERE TARGET INSTANCE ISA 'Win32_LogicalDisk' tells WMI that we only want events that created a new instance of the Win32_LogicalDisk class.

Finally, the –action parameter is a script block—enclosed in {braces}—that contains the action we want to occur when the event is raised.

Using the –computerName parameter to register for events that occur on a remote computer is a neat trick. You need to be a local Administrator on the remote computer, and the action will happen on your computer, not on the remote one.

As an aside, don’t be tempted to register for instance creation events on the CIM_DataFile class that represents files on disk. WMI isn’t very efficient at monitoring new file creation. It will likely miss events, and can impose some pretty heavy overhead in trying to catch everything.

Caveats and Tricks

Of course, responses to your events will only continue for as long as the shell is running. When you close the shell or it closes on its own for some reason, the event registration is gone.

That makes WMI events somewhat less useful for running on users’ machines, because you’re unlikely to have the shell up and running on everyone’s computer at all times. This can be a very useful trick, though, for monitoring processes or other elements on servers where you have more control

Within the –action scriptblock, you have access to an automatic variable called $args, which contains any arguments that are passed from the event. Use Write $args in your –action scriptblock to see what arguments exist for a given WMI event.

Read a bit more about WMI events, and related shell commands, on the TechNet WMI Event Monitoring page.

Don Jones

Don Jones* is a founder of Concentrated Technology, and answers questions about Windows PowerShell and other technologies at ConcentratedTech.com. He’s also an author for Nexus.Realtimepublishers.com, which makes many of his books available as free electronic editions through his web site.*