Learn about Windows PowerShell
Summary: Learn how to use a Windows PowerShell module to work with WMI permanent events.
Hey, Scripting Guy! Your posts this week on permanent event consumers have been really cool. I am wondering, if they are so useful, why there is not a Windows PowerShell cmdlet to allow one to interact with them?
Hello ST, Microsoft Scripting Guy Ed Wilson here. As a matter of fact, Trevor Sullivan was thinking the same thing. One of the great things about Windows PowerShell is that if you do not like it, you can change it. Another great thing is that if something is missing, you can frequently write your own. With Windows PowerShell 2.0 modules, the code that you write (or find) can be adapted to behave in the same manner as a Windows PowerShell cmdlet. I will let Trevor introduce himself and his module. Take it away.
Hello, my name is Trevor Sullivan. I’ve been working on a Windows PowerShell module recently that makes working with Windows Management Instrumentation (WMI) permanent event registrations much easier! The name of this module is PowerEvents — appropriately named to combine Windows PowerShell and WMI eventing. You can download this module for free, from http://powerevents.codeplex.com, and there is ample documentation in the form of a PDF document, YouTube videos, and the CodePlex.com wiki.
There were several reasons that I began developing this module. First and foremost, I wanted to make working with WMI permanent event registrations easy from Windows PowerShell. Second, I have noticed over time that many people seem interested in responding to system-level events, by running some Windows PowerShell code, a VBScript, or an executable. Occasionally, I’ll come across forum posts, or e-mails on a mailing list, where someone wants something to occur in response to an event. Usually the person knows what they want to respond to, and what they want to occur, but perhaps are unaware of WMI events. To summarize, the secondary reason I developed this module, was to help spread the knowledge of WMI events, and to help make them easier for people to understand. Perusing through developer documentation on MSDN is not always what people would consider “easy.”
To satisfy the requirements of these requests, it is sometimes sufficient to use temporary event registrations in WMI. In Windows PowerShell, this is made quite easy using the Register-WmiEvent cmdlet. This cmdlet is included in Windows PowerShell 2.0. It is also relatively easy to use temporary event registrations in a VBScript or C# program. Nevertheless, you must write a fair amount of code to get these working. What is arguably the largest downside to using temporary event registrations, is that they only survive as long as the program (or, process) hosting them (eg. cscript.exe, if you are using a VBScript).
Unlike temporary event registrations, permanent event registrations are created purely inside WMI. Because the WMI process (wmiprvse.exe) is running constantly as a background service, these event registrations are always in effect, unless you explicitly remove them. Be aware that this does not replace an enterprise monitoring solution, but with some creativity on your part, you can easily automate your IT environment. In fact, you could even use the same concepts to automate event-driven actions on your home computers!
As previously discussed, PowerEvents intends to make working with WMI permanent event registrations easy. To that end, it provides several Windows PowerShell advanced functions to create the three necessary WMI objects, to create an end-to-end event Registration:
With a simple three lines of Windows PowerShell, you can create a filter, a consumer, and the binding between the two. Because these are advanced functions, you can use tab completion for the parameter names. You can also get help on the functions and their parameters by using Get-Help <FunctionName> or Get-Help <FunctionName> -Full.
The first step to creating a permanent event registration is coming up with the events that you want to capture! This should be easy, since it is usually the first thing on most people’s minds. You can monitor things such as:
You use the New-WmiEventFilter function to create an event filter, makes sense, right? Remember that with Windows PowerShell, it’s think, type, get. All that you have to do is give a helpful name to the event filter (using the -Name parameter), and provide the WMI Query Language (WQL) event filter that you want to use. Assign the output of the New-WmiEventFilter function to a Windows PowerShell variable, because you will need it later to create the Filter/Consumer binding.
Here is an example of creating a WMI event filter:
New-WmiEventFilter -Name UserProfileLoaded -Query "select * from __InstanceModificationEvent within 2 where TargetInstance ISA 'Win32_UserProfile' and TargetInstance.Loaded <> PreviousInstance.Loaded and TargetInstance.Loaded = TRUE"
As you can see, we gave the filter a useful name that describes its purpose. We then passed our event query to the –Query parameter. That’s it!
Now that you have created an event filter, the next step is to create an event consumer to respond to the events!
New-WmiEventConsumer is the most complex of the three functions, but don’t worry, it’s simple. Because it wraps the functionality of five event consumers included in Windows, there are a large number of parameters. Do not get overwhelmed by all the parameters, because in most cases, you will only have to specify a couple of them. The ConsumerType and Name parameters are most important, and are common to all consumer types. Beyond these two parameters, the others will depend on the consumer type that you want to use.
There are five consumer types that you can select from: SMTP, LogFile, EventLog, Script, and CommandLine. For most purposes, the Script and CommandLine consumers will probably be the most useful to you, because they are the most flexible in how you respond to an event.
Here is an example of creating a script consumer:
$VBcode = @"
set fso = CreateObject("Scripting.FileSystemObject")
set LogFile = fso.OpenTextFile("c:\Printer.log", 8, true)
call LogFile.WriteLine(Date() & " " & Time() & ": Print job created")
New-WmiEventConsumer -Name PrintJobCreated -ConsumerType Script -ScriptText $VBcode
The VBscript we want to run is contained within a Windows PowerShell here-string, and then we call New-WmiEventConsumer, give it a useful name, tell it we are creating a Script consumer type, and then pass in the $VBcode we defined.
WMI event filters and consumers are completely independent entities from one another unless you create a binding between them. The binding initiates the flow of events through the WMI eventing subsystem, and allows you to specify exactly what action should occur in response to an event coming from an event filter.
The New-WmiFilterToConsumerBinding function allows you to create the binding between a filter and a consumer. It has two main parameters, –Filter and –Consumer. To use this function, pass a reference to an event filter to –Filter, and a reference to a consumer to –Consumer.
$MyConsumer = New-WmiEventConsumer … … …
$MyFilter = New-WmiEventFilter … … …
New-WmiFilterToConsumerBinding –Filter $MyFilter –Consumer $MyConsumer
Here, we create a consumer, and store it in a variable, then create a filter and store it in a variable, and finally create the binding between the two using New-WmiFilterToConsumerBinding.
Today, we introduced the PowerEvents module for Windows PowerShell, and talked about the three main functions that it contains. In tomorrow’s blog post, we will examine some specific examples of using the PowerEvents module to create permanent WMI event registrations. Thanks for reading!
ST, that is all there is to using the Windows PowerShell event module. Permanent event consumer week will continue tomorrow when Trevor will talk about how to incorporate his module.
I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at email@example.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy