More Event Scripting with WMI

In the first article of this series we saw how WMI can be used to build an event driven script. In this segment we will be learning what other events WMI makes available to us. Let’s get started.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 3
May 15, 2007
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Before we begin, let’s take another look at the code from the last article.  We’ll be using that as the base for all of the samples in this one.

strComputer = "."

Set objWMIService = GetObject("winmgmts:" & strComputer _

   & "rootcimv2")

 

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _

      & "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _

      & "TargetInstance.GroupComponent= " _

      & "'Win32_Directory.Name=""c:\test""'")

 

Do While True

   Set objEvent = colEvents.NextEvent()

   WScript.Echo "File Deleted:", _

       objEvent.TargetInstance.PartComponent

Loop

As we’ve learned, this code watches the C:test folder for file deletions.  We connect to the WMI service, issue an event based query, and then process the results in an endless Do…Loop.

The important things to note here are the use of the __InstanceCreationEvent event and the use of the NextEvent function to move through returned events.

We’re going to be using this same construct with our next event.  We’ll simply plug in a new event and the code will function in an identical fashion.

We know how to watch for creations.  We also know how to watch for deletions.  The third event type we’ll be looking at will watch for modifications.  Again, our examples will be watching for files, but this could easily be altered to watch for changed registry keys or any other scriptable object.

Using __InstanceModificationEvent

We’ll be using the __InstanceModificationEvent event.  This event watches an object for any modifications.  These include: changing the object name, adding or removing content, or altering any attributes.  Essentially, it watches for any time the object is changed or modified in any way.

This is useful for watching a file or folder for updates, or watching specific registry keys for unwanted changes.

To implement this event, simply use a drop-in replacement in our code sample.

strComputer = "."

Set objWMIService = GetObject("winmgmts:" & strComputer _

   & "rootcimv2")

 

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE " _

      & "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _

      & "TargetInstance.GroupComponent= " _

      & "'Win32_Directory.Name=""c:\test""'")

 

Do While True

   Set objEvent = colEvents.NextEvent()

   WScript.Echo "File Modified:", _

       objEvent.TargetInstance.PartComponent

Loop

You can test this by again creating a folder called C:test.  Create a plain text file.  (It doesn’t matter what you name it.)  Now run your script.  While your script is running, open the text file in Notepad and add some text.  Now save your changes.  You script should notify you that the file has been changed.

As you’ve probably noticed by now, WMI returns a pretty interesting file path.

ComputerNamerootcimv2:CIM_DataFile.Name="c:scriptsDocument.txt"

This is probably not what you want.  Let’s take a quick look at how to parse this into a usable file path.

Parsing WMI’s results

As you can see, WMI returns a full WMI path to the object.  Since this is returned as a string, we can create a function to parse the data.

Function parsePath(strWMIpath)

   strPath = Right(strWMIpath, Len(strWMIpath) - InStr(strWMIpath, "="))

   strPath = Left(strPath, Len(strPath) - 1)

   strPath = Right(strPath, Len(strPath) - 1)

   strPath = Replace(strPath, "", "")

   parsePath = strPath

End Function

Okay, there’s lot of things going on here.  Let me try to explain what’s happening.  If you look at the string path returned by WMI you will see that we only need the information to the right of the equal sign.  So the first part returns just that.

We use the InStr function to return the position of the equals sign.  By subtracting that number from the total length of the string, we can determine how many characters appear after it.  Then we use the Right function to return only that portion of the string.

"c:scriptsDocument.txt"

Now we have our file path.  However, it’s enclosed in quotation marks.  We probably wouldn’t want that either so we use the next two lines to clip a single character from each side of the string.

c:scriptsDocument.txt

This leaves us with our file path, but there’s still one more problem.  Our file path still contains WMI’s escaped backslashes.  To eliminate those, we’ll use VBScript’s Replace function to replace all occurrences of a double backslash with a single one.

c:scriptsDocument.txt

Now strPath contains only our formatted file path.  We wrap up our function by telling it to return the contents of strPath.

Now to implement this in our code we need to make one minor change inside of our Do…Loop.  Rather than echoing back WMI’s path, we need to pass it through our function first.

Do While True

   Set objEvent = colEvents.NextEvent()

   WScript.Echo "File Modified:", _

       parsePath(objEvent.TargetInstance.PartComponent)

Loop

Now our script returns exactly the information we wanted.  If we wanted, we could pass this path on to FileSystemObject method, for example, to back up the newly modified file.  Or, as in our example, we simply echo it back.

Using __InstanceOperationEvent

So now we’ve learned how to implement WMI events to watch for creations, deletions, and modifications.  By now you’re probably wondering what you can do if you want to watch for any or all of these events at the same time.

Let’s take this code as an example.

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceCreationEvent OR __InstanceDeletionEvent " _

       & WITHIN 10 WHERE " _

      & "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _

      & "TargetInstance.GroupComponent= " _

      & "'Win32_Directory.Name=""c:\test""'")

In this query we’ve instructed WMI to look for either a creation event or a deletion event.  It seems simple enough, but there’s one problem.  It won’t work.

WMI will issue an “Unparsable query” error when you try to do this.  As it turns out, WMI only likes to deal with one event at a time.  This is a very logical script so how can we solve this problem?

Enter WMI’s fourth and final event type.  The __InstanceOperationEvent event will monitor for any of the creation, deletion, or modification events.  It works a little bit differently though.

You’re going to start out with the same code construct.  Simply drop the new event into your query.

strComputer = "."

Set objWMIService = GetObject("winmgmts:" & strComputer _

   & "rootcimv2")

 

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE " _

      & "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _

      & "TargetInstance.GroupComponent= " _

      & "'Win32_Directory.Name=""c:\test""'")

Here’s where things get a little tricky.  The __InstanceOperationEvent still returns a collection of events, and we’re still going to process them with an endless do loop.  But now we have to determine which event has occurred.  We’ll do that by setting up a Select statement for each event type we're looking for.

Do While True

   Set objEvent = colEvents.NextEvent()

  

   Select Case objEvent.Path_.Class

       Case "__InstanceCreationEvent"

          WScript.Echo "File Created:", _

          parsePath(objEvent.TargetInstance.PartComponent)

       Case "__InstanceDeletionEvent"

          WScript.Echo "File Deleted:", _

          parsePath(objEvent.TargetInstance.PartComponent)

       Case "__InstanceModificationEvent"

          WScript.Echo "File Modified:", _

          parsePath(objEvent.TargetInstance.PartComponent)

   End Select

Loop

The key to this whole code segment is the use of the Path_.Class property.  This property contains the type of event that was returned.  The Select Case statement chooses how to process the event based on what type it was.  If we were only concerned with creation and deletion events, we could simply omit the Case statement for modified ones.

If you were looking for changes to a specific file, you would want to implement an If statement to check the file name.  This is just a base script and should be customized to fit your needs.

The topics in this series are quite advanced.  You should play around with them to get a good handle on what’s really happening behind the scenes.  Once you understand the concept, you’ll find that building your own customized script isn’t as daunting a task as it might seem.

Making use of event driven programming will open many possibilities to you as a programmer.  You now have the power to create scripts capable of reacting to the system in real time.  Now go explore and see what you can come up with.  Until next time…keep coding!

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 10 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials