Contents
- Introduction
- WQL Event Queries
- Event Helper Classes
- WITHIN and GROUP Clauses
- Temporary Event Consumers
- Permanent Event Subscription
- Using WMI Tools
- ActiveScriptEventConsumer Class
- Note about Strings
- TargetEvent and TargetInstance
- SMTPEventConsumer Class
- LogFileEventConsumer Class
- CommandLineEventConsumer Class
- Win32_LocalTime Class
- Final Note
- Useful Links
1. Introduction
The WMI Event Subsystem allows you to subscribe to WMI events. WMI events represent changes in WMI data: if you start Notepad, an instance of the
Win32_Process WMI class is created, and an instance creation WMI event is also created. If you delete a file from the disk, an instance of the CIM_DataFile class is deleted, and an instance deletion WMI event is created. In fact, any change in WMI data can be used to create an event, so it is easy to see how WMI events can be useful in system administration.
WMI will not create events for you unless you subscribe to them. Applications that register their interest in WMI events are called event consumers.
There are two types of event consumers: temporary and permanent. Temporary event consumers are typically applications that use the .NET Framework and its
System.Management namespace or WMI scripting library to receive WMI events, which means that they receive events only when they are started by a user. Permanent event consumers are different - they are designed to receive events at all times. Both temporary and permanent event consumers use WMI event queries to subscribe to events they are interested in.2. WQL Event Queries
Just like other WMI queries, WMI event queries are issued using WQL (WMI Query Language). There are several differences between event queries and other query types, but the most significant one is that WMI event queries use WMI event classes. A WMI class is an event class if it is derived from the
__Event system class. So, in order to see what tasks can be accomplished using WMI events, you first need to examine the WMI event classes. But, how can you do that? Since all event classes are derived from the __Event system class, you can use a query like this one:Select * From Meta_Class Where __This Isa "__Event"
Although this query includes a reference to the
__Event class, it is not an event query. Actually, it is a WMI schema query - it uses Meta_Class, a special class that represents all classes in a WMI namespace. Since you don't want all the classes, but just the __Event derived classes, you also need to add the WHERE clause. When issued, the query returns a list of WMI classes that looks like this:. . .
MSFT_WMI_GenericNonCOMEvent
MSFT_WmiSelfEvent
Msft_WmiProvider_OperationEvent
Msft_WmiProvider_ComServerLoadOperationEvent
Msft_WmiProvider_InitializationOperationFailureEvent
Msft_WmiProvider_LoadOperationEvent
Msft_WmiProvider_OperationEvent_Pre
Msft_WmiProvider_DeleteClassAsyncEvent_Pre
Msft_WmiProvider_GetObjectAsyncEvent_Pre
Msft_WmiProvider_AccessCheck_Pre
Msft_WmiProvider_CreateClassEnumAsyncEvent_Pre
Msft_WmiProvider_ExecQueryAsyncEvent_Pre
Msft_WmiProvider_CreateInstanceEnumAsyncEvent_Pre
Msft_WmiProvider_NewQuery_Pre
Msft_WmiProvider_DeleteInstanceAsyncEvent_Pre
Msft_WmiProvider_CancelQuery_Pre
Msft_WmiProvider_PutInstanceAsyncEvent_Pre
. . .
On my test Windows XP SP2 machine, the query returns a total of 136 classes. The number may be different on your computer, but if you examine the list closely, you'll notice that most commonly used WMI classes like
Win32_Process or Win32_Service are not on it.3. Event Helper Classes
So, the classes that you are really interested in are not derived from the
__Event class, but it is still possible to use them in WMI event queries. You can use all WMI classes in event queries, only not directly. In order to use a class that is not derived from __Event in an event query, you need to use one of the helper classes like:__InstanceCreationEvent__InstanceModificationEvent__InstanceDeletionEvent
All of the above classes are derived from
__InstanceOperationEvent, and have a TargetInstance property, which is a reference to the class instance you want to receive event notifications from. So, if you use a query like this:Select * From __InstanceCreationEvent
Where TargetInstance Isa "Win32_Process"
the
TargetInstance property of the returned event will contain a reference to the Win32_Process instance that was created. If you want to refer to the Win32_Process.ExecutablePath property, use the__InstanceCreationEvent.TargetInstance.ExecutablePath property. In addition, the__InstanceModificationEvent class has the PreviousInstance property that contains a reference to a copy of the WMI class instance before it was modified. Classes derived from __InstanceOperationEvent and theirTargetInstance property enable you to use all WMI classes in event queries.4. WITHIN and GROUP Clauses
The WMI event subsystem uses a polling mechanism for event delivery. To specify the polling interval, use the
WITHIN keyword followed by the polling interval (in seconds):Select * From Win32_Process
Within 10
Where TargetInstance Isa "Win32_Process"
In this example, WMI initially enumerates all
Win32_Process instances, and polls for changes every ten seconds. This means that it is possible to miss some events: if a process is created and destroyed in less than ten seconds, it will not raise an event.
The
Group clause causes WMI to create only one event notification to represent a group of events. For example, this query:Select * From __InstanceModificationEvent
Within 10
Where TargetInstance Isa
"Win32_PerfFormattedData_PerfOS_Processor"
Group Within 5
Having NumberOfEvents > 3
will create one event that represents all the modification events for
Win32_PerfFormattedData_PerfOS_Processor that occurred within 5 seconds, but only if the number of events is greater than 3.
To summarize:
- WQL event queries use classes derived from the
__Eventsystem class. - WQL event queries use
WithinandGroupclauses. - WQL event queries use the
Isakeyword to specify classes to receive events from. - WQL event queries use
TargetInstanceandPreviousInstanceto access WMI data of interest.
5. Temporary Event Consumers
A temporary event consumer is any application that requests event notifications from WMI. In most cases, it is a VBScript or code that uses the
System.Management namespace. Here is a sample VBScript that subscribes to theWin32_Process creation events:' VBScript source code
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "\\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService. _
ExecNotificationQuery("select * from __InstanceCreationEvent " _
& " Within 1 Where TargetInstance isa 'Win32_Process'")
Do
Set objLatestProcess = colMonitoredProcesses.NextEvent
Wscript.Echo objLatestProcess.TargetInstance.Name
Loop
Although this code works, it has at least three disadvantages:
- The script process needs to run all the time. The above script will receive WMI events only while it is running, and while it is running, it consumes system resources. This may become a problem if you have multiple scripts running at the same time.
- The process can be easily interrupted. Scripts such as the above are typically run from the Command Prompt, so they can easily be interrupted, either by closing the Command Prompt box, or by pressing Ctrl+C.
- Even if the CScript process is interrupted, the event notification is not canceled. This may be the most serious disadvantage.
Here is a sample of the third case:
' VBScript source code
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "\\" & strComputer & "\root\cimv2")
Set colEvents = objWMIService.ExecNotificationQuery _
("Select * From __InstanceCreationEvent Within 2" _
& "Where TargetInstance Isa 'Win32_Directory' " _
& "And TargetInstance.Path = '\\Scripts\\'")
Do
Set objEvent = colEvents.NextEvent()
WScript.Echo objEvent.TargetInstance.Name
Loop
Scripts like this one are typically run from the Command Prompt. But, even if you stop the script, the event notification is not canceled - you can easily observe that, because the floppy disk drive is still flashing every two seconds (I call this the 'FDD Light Show'). This is true not only of the file system monitoring scripts, but every other. The only way to cancel the event notification in this case is to stop the Winmgmt service itself, using:
net stop winmgmt
The Windows Firewall service depends on Winmgmt, so it is easy to imagine a situation where this can become a problem.
6. Permanent Event Subscription
WMI permanent event subscription can remedy all these problems. It doesn't depend on a running process (save forsvchost.exe that hosts the Winmgmt service). To interrupt it, you need knowledge of WMI, so it is not easy to stop it accidentally, and you can cancel it anytime, without having to restart the Winmgmt service. In its basis, permanent event subscription is a set of static WMI classes stored in a CIM repository. Of course, you can use VBScript or the .NET Framework
System.Management classes to create these instances and set up a permanent event subscription, but the easiest way is (at least in my opinion) to use MOF. Here is a sample MOF that you can use as a template for creating permanent event subscriptions:// 1. Change the context to Root\Subscription namespace
// All standard consumer classes are
// registered there.
#pragma namespace("\\\\.\\root\\subscription")
// 2. Create an instance of __EventFilter class
// and use it's Query property to store
// your WQL event query.
instance of __EventFilter as $EventFilter
{
Name = "Event Filter Instance Name";
EventNamespace = "Root\\Cimv2";
Query = "WQL Event query text";
QueryLanguage = "WQL";
};
// 3. Create an instance of __EventConsumer
// derived class. (ActiveScriptEventConsumer
// SMTPEventConsumer etc...)
instance of __EventConsumer derived class as $Consumer
{
Name = "Event Consumer Instance";
// Specify any other relevant properties.
};
// 4. Join the two instances by creating
// an instance of __FilterToConsumerBinding
// class.
instance of __FilterToConsumerBinding
{
Filter = $EventFilter;
Consumer = $Consumer;
};
To create a permanent WMI event subscription, you need to follow these steps:
- Change the WMI context to the
Root\Subscriptionnamespace. Starting with Windows XP, it is Microsoft's recommendation to store all permanent event subscriptions there. - Create an instance of the
__EventFilterclass. The__EventFilterclass is derived from the__IndicationRelatedsystem class, and its main purpose is to hold a WQL event query. To create an instance of__EventFilter, use 'instance of' keywords. First, you give the class instance a unique name using itsNameproperty. Second, specify itsEventNamespaceproperty - typically, this will be theRoot\Cimv2namespace, as the majority of useful classes are located there. Third, set itsQueryproperty to the WQL event query you want to use. - Create an instance of the
__EventConsumerderived class. This is the instance that represents the event consumer. Although it is possible to create custom__EventConsumerderived classes, this requires creating a COM object that reacts to the specified event, which is probably not a viable solution for most system administrators. Luckily, Microsoft provides a set of standard event consumer classes, likeActiveScriptEventConsumer,LogFileEventConsumer, etc. In this article, I will use only standard event consumer classes. - Associate the instances of
__EventFilterand__EventConsumerderived classes by creating an instance of the__FilterToConsumerBindingclass. ItsFilterproperty is a reference to the previously created instance of the__EventFilterclass, and itsConsumerproperty is a reference to one of the standard event consumer class instances.
In the rest of this article, I will attempt to walk you through several samples of permanent event subscription that use standard event consumer classes.
7. Using WMI Tools
A tool named WMI Event Registration is included with WMI Tools, and it is very helpful when working with permanent subscription: it allows you to explore existing filters, consumers, or timers, and also create new ones using a user-friendly interface. You can also cancel event subscriptions using this tool.
When this tool is first opened, you are offered to connect to the
Root\Cimv2 namespace, but connect toRoot\Subscription instead - this is where you will create most of the permanent event subscriptions. Once connected, if you select 'Consumers' from the leftmost dropdown, you will see a list of all available standard event consumer classes listed in the left hand pane, as they are already registered there.
If an instance of any of the standard event consumer classes already exists, by selecting it, you can view the available
__EventFilter instances in the right hand pane. If any of the __EventFilter instances is joined with the selected consumer instance, it is checked, so, the green checkmark actually represents an instance of the__FilterToConsumerBinding class.
All permanent event subscription samples presented here are created using MOF - you need a tool calledmofcomp.exe to store instance definitions contained in a MOF file into the CIM repository. Mofcomp.exe is stored in the Windows directory (typically C:\Windows\System32\Wbem\) and its basic syntax is:
mofcomp FileName.mof
8. ActiveScriptEventConsumer Class
The
ActiveScriptEventConsumer class is one of the standard event consumer classes: it allows you to run ActiveX script code whenever an event is delivered to it. To create an instance of theActiveScriptEventConsumer class, you need to assign values to its properties:Name: Gives a unique name to an instance ofActiveScriptEventConsumer.ScriptingEngine: This is the name of the scripting engine that will be used. Although the documentation states that this can be any arbitrary scripting engine, the only ones I have used are 'VBScript' and 'JScript'.ScriptText: This is a string property that contains a VBScript or JScript code to be executed when an event is delivered to theActiveScriptEventConsumerinstance.ScriptFileName: This property holds the full path to the VBScript or JSCript file to be executed on event arrival.ScriptTextandScriptFileNameproperties are mutually exclusive.
As a test, you can create an event consumer that executes some arbitrary VBScript code whenever an instance of
Win32_Process named 'notepad.exe' is created. To create a permanent event subscription that usesActiveScriptEventConsumer:- Change the current WMI namespace to
Root\Subscription:Collapse | Copy Code
#pragma namespace("\\\\.\\root\\subscription") - Create an instance of the
__EventFilterclass to monitor theWin32_Processcreation:Collapse | Copy Code
instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "New Process Instance Filter"; Query = "Select * From __InstanceCreationEvent Within 2" "Where TargetInstance Isa \"Win32_Process\" " "And Targetinstance.Name = \"notepad.exe\" "; QueryLanguage = "WQL"; };In this case, you will receive a__InstanceCreationEventclass instance, but from theRoot\Cimv2namespace, as theWin32_Processclass is located there. - Create an instance of the
ActiveScriptEventConsumerclass:Collapse | Copy Code
instance of ActiveScriptEventConsumer as $Consumer { Name = "TestConsumer"; ScriptingEngine = "VBScript"; ScriptText = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n" "Set objFile = objFSO.OpenTextFile(\"c:\\log.txt\", 8, True)\n" "objFile.WriteLine Time & \" \" & \" Notepad started\"\n" "objFile.Close\n"; };The VBScript code that is assigned to itsScriptTextproperty simply logs the time of the notepad.exeprocess creation to a text file. - Bind the two previously created instances using the
__FilterToConsumerBindingclass:Collapse | Copy Code
instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; }
When you compile the above MOF using mofcomp.exe, every time Notepad is opened, the time of the notepad.exeprocess creation is logged to the c:\log.txt file. If the file doesn't already exist, it is created when the first event notification is received.
Instead of
ScriptText, you can also use the ScriptFileName property:instance of ActiveScriptEventConsumer as $Consumer
{
Name = "ExternalScriptConsumer";
ScriptingEngine = "VBScript";
ScriptFileName = "C:\\Consumer.vbs";
};
In that case, you also need an external script file: c:\Consumer.vbs.
When creating VBScript or JScript scripts to use with
ActiveScriptEventCosumer, you need to be aware of some limitations:ActiveScriptEventConsumerdoesn't use the Windows Script Host (WSH), which is widely used in system administration scripts. This means that you can not use theWScriptobject or any of its properties and methods (likeWScript.CreateObject,WScript.Sleepetc.).- The script can not generate any screen output, which means that you can not use the VBScript
MsgBoxfunction. - The script does not have network access.
- The script can't use any user specific data, such as environment variables or network shares.
9. Note about Strings
When setting up a permanent event subscription, it is likely that you will need to use strings, so here is a quick note:
An MOF string is a sequence of characters enclosed in double quotes. Successive strings are joined together, so this:
"Select * From __InstanceCreationEvent "
"Within 30 "
becomes:
"Select * From __InstanceCreationEvent Within 30 "
You can also use the following escape sequences:
\b backspace
\t horizontal
\n linefeed
\f form feed
\r carriage return
\" double quote
\' single quote
\\ backslash
10. TargetEvent and TargetInstance
A script executed by an
ActiveScriptEventConsumer instance can access an environment variable calledTargetEvent, which holds a reference to the event class:instance of ActiveScriptEventConsumer as $Consumer
{
Name = "TargetEventConsumer";
ScriptingEngine = "VBScript";
ScriptText =
"Const ForReading = 1\n"
"Const ForWriting = 2\n"
"\n"
"Set objFso = CreateObject(\"Scripting.FileSystemobject\")\n"
"Set objStream = objFso.OpenTextFile( _\n"
" TargetEvent.TargetInstance.Name, ForReading, False)\n"
"\n"
"strContent = objStream.ReadAll()\n"
"objStream.Close\n"
"\n"
"Set objStream = objFso.OpenTextFile( _\n"
" TargetEvent.TargetInstance.Name, ForWriting, False)\n"
"\n"
"objStream.Write( _\n"
" Replace(strContent, \"127.0.0.1\", \"Localhost\"))\n"
"objStream.Close\n";
};
The event class is typically one of various
__InstanceOperationEvent derived classes, whose TargetInstanceproperty, in turn, is a reference to the actual class instance of what was created. If that class is, for example,CIM_DataFile, you need to use the following to access its Name property:TargetEvent.TargetInstance.Name
11. SMTPEventConsumer Class
This class sends an e-mail message each time an event is delivered to it. To create an instance of the
SMTPEventConsumer class, assign values to its properties:Name: Gives a unique name to the instance.SMTPServer: Name of the SMTP server through which the message will be sent.ToLine: To line of the e-mail message.FromLine: From line of the e-mail message.Subject: Subject line of the mail message.Message: The body of the e-mail message.
As an example, set up a permanent event subscription that uses the
SMTPEventConsumer class to send an e-mail message each time a printer status changes. To use SMTPEventConsumer in permanent event subscription:- Change the context to the
Root\Subscriptionnamespace:Collapse | Copy Code
#pragma namespace("\\\\.\\root\\subscription") - Create an instance of the
__EventFilterclass:Collapse | Copy Code
instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "SMTPEventFilter"; Query = "Select * From __InstanceModificationEvent " "Within 2 " "Where TargetInstance Isa \"Win32_Printer\" " "And (TargetInstance.PrinterStatus = 1 " "Or TargetInstance.PrinterStatus = 2) " "And Not (PreviousInstance.PrinterStatus = 1 " "Or PreviousInstance.PrinterStatus = 2)"; QueryLanguage = "WQL"; };With the above WQL query, you subscribe to modification events of theWin32_Printerclass instances. Note the usage of the__InstanceModificationEvent.PreviousInstanceproperty, which contains a copy of theWin32Printerinstance before it was changed. It is useful for comparing the instance properties before and after it was modified. In this case, we are only interested in the events in which theWin32_Printer.PrinterStatusvalue is changed from anything else to 1 or 2. - Create an instance of the
SMTPEventConsumerclass:Collapse | Copy Code
instance of SMTPEventConsumer as $Consumer { Name = "Printer Error Event Consumer"; SMTPServer = "SMTPServerName"; ToLine = "Recipient@nn.com"; FromLine = "Sender@nn.com"; Subject = "Printer Error!"; Message = "An error is detected in one of the printers!\n" "Printer Name: %TargetInstance.Name%\n" "Server: %TargetInstance.__Server%\n" "Event Date: %TIME_CREATED%"; };If you look at theSMTPEventConsumerclass MOF code, you will see that most of its properties are marked with aTemplatequalifier. This means that you can use WMI standard string templates when setting their values. Using standard string templates, you can access the event class properties, just as you can use theTargetEventenvironment variable withActiveScriptEventConsumer. So, for example, ifTargetInstanceisWin32_Printer, this:
Collapse | Copy Code
"Printer Name: %TargetInstance.Name%"will be translated into something like:
Collapse | Copy Code
"Printer Name: HP LaserJet III PostScript Plus v2010.118"Also, this:
Collapse | Copy Code
"Event Date: %TIME_CREATED%"will become:
Collapse | Copy Code
"Event Date: 128611400690000000"__InstanceModificationEvent.Time_Createdis the number of 100-nanosecond intervals after January 1, 1601, so if you want to convert it to a readable format, it will probably take a bit of work. - Bind the two instances by creating an instance of the
__FilterToConsumerBindingclass:Collapse | Copy Code
instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
12. LogFileEventConsumer Class
The
LogFileEventConsumer class writes customized strings to a text file each time an event is delivered to it. Significant properties:Name: Gives a unique name to the instance.Text: Contains the text to be written to the log file when an event arrives. You can use standard string templates to compose it.Filename: Path to the text file where the value of theTextproperty is to be written.
A sample usage of
LogFileEventConsumer could be to log changes in a Windows service's state. To useLogFileEventConsumer with permanent event subscription:- Change the context to the
Root\Subscriptionnamespace:Collapse | Copy Code
#pragma namespace("\\\\.\\root\\subscription") - Create an instance of the
__EventFilterclass that monitors theWin32_Servicemodification events:Collapse | Copy Code
instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "Service State Event Filter"; Query = "Select * From __InstanceModificationEvent " "Within 2 " "Where TargetInstance Isa \"Win32_Service\" " "And TargetInstance.State <> " "PreviousInstance.State"; QueryLanguage = "WQL"; }; - Create an instance of
LogFileEventConsumer:Collapse | Copy Code
instance of LogFileEventConsumer as $Consumer { Name = "Service State Log Consumer"; Filename = "c:\\scripts\\ServiceStateLog.csv"; IsUnicode = true; Text = "\"%TargetInstance.Name%\"," "\"%PreviousInstance.State%\"," "\"%TargetInstance.State%\"," "\"%TIME_CREATED%\""; }; - Bind the two instances using the
__FilterToConsumerBindingclass:Collapse | Copy Code
instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
When assigning value to the
LogFileEventConsumer.Text property, use WMI standard string templates to access event-related data.13. CommandLineEventConsumer Class
The
CommandLineEventConsumer class launches an arbitrary process when an event is delivered to it. Important properties are:Name: Gives a unique name to the instance.ExecutablePath: Path to the executable. This property can beNull, but even if you assign a value to it, you still need to include the executable path at the beginning of theCommandLineTemplateproperty.CommandLineTemplate: Standard string template that specifies the executable to be launched, followed by any command line arguments. You can use standard string templates when creating it.
Here is a sample of a
CommandLineEventConsumer MOF that monitors PNP device changes. To create a permanent event subscription that uses CommandLineEventConsumer:- Change the WMI context to the
Root\Subscriptionnamespace:Collapse | Copy Code
#pragma namespace("\\\\.\\root\\subscription") - Create an instance of the
__EventFilterclass that detects theWin32_PNPEntityinstance creation:Collapse | Copy Code
instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "Test Command Line Event Filter"; Query = "Select * From __InstanceCreationEvent " "Within 2 " "Where TargetInstance Isa \"Win32_PNPEntity\" "; QueryLanguage = "WQL"; }; - Create an instance of the
CommandLineEventConsumerclass:Collapse | Copy Code
instance of CommandLineEventConsumer as $Consumer { Name = "Test CommandLine Event Consumer"; RunInteractively = false; CommandLineTemplate = "cmd /c " "WMIC /Output:" "C:\\HWLogs\\PNPDeviceLog%TIME_CREATED%.html " "Path Win32_PNPEntity " "Get Caption, DeviceId, PNPDeviceId " "/Format:HTable.xsl"; };ThisCommandLineEventConsumerinstance uses the WMI command line utility (WMIC) to create a simple HTML file that contains a list of allWin32_PNPEntityinstances each time a newWin32_PNPEntityinstance is created. - Bind the instances using
__FilterToConsumerBinding:Collapse | Copy Code
instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
14. Win32_LocalTime Class
The
Win32_LocalTime class is an exception: it is not derived from the __Event class, but you can still use it in WQL event queries, which means that you can also use it to set up a permanent event subscription. An interesting use of the Win32_LocalTime class can be to mimic the Windows Scheduler service. To create a permanent event subscription that subscribes to Win32_LocalTime events:- Change the context to the
Root\Subscriptionnamespace:Collapse | Copy Code
#pragma namespace("\\\\.\\root\\subscription") - Create an instance of the
__EventFilterclass:Collapse | Copy Code
instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "Sample Timer Event Filter"; Query = "Select * From __InstanceModificationEvent " "Where TargetInstance Isa \"Win32_LocalTime\" " "And TargetInstance.Hour = 18 " "And TargetInstance.Minute = 10 " "And TargetInstance.Second = 30"; QueryLanguage = "WQL"; };Use this filter to subscribe toWin32_LocalTimemodification events. In the query, you can use any combination ofWin32_LocalTimeproperties:Day,DayOfWeek,Hour,Milliseconds,Minute,Month,Quarter,Second,WeekInMonth, andYear. - Create an instance of a
__EventConsumerderived class:Collapse | Copy Code
instance of CommandLineEventConsumer as $Consumer { Name = "Test CommandLine Event Consumer"; RunInteractively = false; CommandLineTemplate = "cmd /c " "C:\\Backup\\LocalBackup.bat"; };In this case, it is an instance of theCommandLineEventConsumerclass, but it can be any of the standard consumer classes. - Bind
__EventFilterandCommandLineEventConsumerinstances by creating an instance of the__FilterToConsumerBindingclass:Collapse | Copy Code
instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
15. Final Note
Permanent event subscription has several advantages over temporary event subscription, but it also has one disadvantage: temporary event subscription is easier to debug. If you are using the
System.Managementnamespace to create an application that subscribes to WMI events, you have all Visual Studio debugging tools at your disposal. If you are using VBScript, you can test WQL event queries separately from the rest of the code, and you receive meaningful (at least sometimes) error messages from WMI. While you are testing permanent event subscription, the only source of debugging information is the WMI event subsystem log file, named Wbemess.log (it is typically located in the C:\Windows\System32\Wbem\Logs\ directory) - all errors detected both in the event filter and the event consumer instances are logged there, and the messages are not always easy to decipher. So, it is probably better to test WQL queries you want to use for permanent event subscription using System.Management or VBScript first.
Permanent event subscription can be useful, but if you don't use it carefully, it can consume too much system resources and become inefficient. There are two ways to deal with this:
- Increase the polling interval using the
Withinclause. In the samples presented here, I used very short polling intervals, but, depending on your requirements, you can increase it at your will. - Make WQL queries more selective using the
Whereclause. For example, this query:Collapse | Copy Code
Select * From __InstanceCreationEvent Where TargetInstance Isa "CIM_DataFile" And TargetInstance.Path = "\\Logs\\"will be less efficient than this one:
Collapse | Copy Code
Select * From __instanceCreationEvent Where TargetInstance Isa "CIM_DataFile" And TargetInstance.Drive = "C:" And TargetInstance.Path = "\\Logs\\" And TargetInstance.Extension = "Log"
Queries that include file system classes like
CIM_DataFile or Win32_Directory can be very resource consuming, in general: a query that monitors a couple of hundreds of files can slow down your system noticeably.
WQL is a version of SQL, and for SQL queries, it is often recommended not to select all fields in a table (using '*') unless you really need all of them. I haven't tested this recommendation with WQL queries, but I don't think this advice applies to WQL.
16. Useful Links
There is not much documentation concerning permanent event subscription, but you can find some in MSDN:
No comments:
Post a Comment