PowerShell Answers

Adventures in PowerShell

About the author

Author Name is someone.
E-mail me Send mail

Recent posts

Recent comments

Don't show

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Configuring WMI Event Handling with PowerShell

PowerShell provides a helpful type accelerator '[WMICLASS]' that makes using these WMI classes extremely easy.

Lets say that we wanted to log to a file every process that was created on a machine.

First we need to create our filter. To do this we connect to the '__EventFilter' class, create a new instance, set it's properties and save it into WMI. Note - you need admin rights to write into the WMI store so you will need to run PowerShell as administrator for these scripts to work. There is no way to provide alternative credentials when you are using the type accelerator. Get-WmiObject does support a credential parameter but it doesn't work on local connections and there's no way to use the credential when you invoke 'Put' on the new class instance.

The code below creates a filter that will check the '\root\cimv2' namespace every 5 seconds for new instances of the 'Win32_Process' class'

$EFClass = [wmiclass]"\root\subscription:__EventFilter"
$ef = $EFClass.CreateInstance()
$ef.Name = "NewProcessFilter"
$ef.Querylanguage = "WQL"
$ef.Query = "select * from __InstanceCreationEvent within 5 where targetinstance isa 'Win32_Process'"
$ef.EventNamespace = "root\cimv2"
$ef.put()

Now we create the event consumer - in this case we're going to use the LogFileEventConsumer. As before we attach to the appropriate class, create an instance, set its properties and store the new instance. Note the use of a string template in the text property. This allows us to pull out properties from the object that caused the event - in this case an instance of Win32_Process.

$ECClass = [wmiclass]"\root\subscription:LogFileEventConsumer"
$lfc = $ECCLass.createinstance()
$lfc.Name = "MyLogFileConsumer"
$lfc.FileName = "c:\temp\Win32Process.log"
$lfc.Text = "Process %TargetInstance.Name% was created on %TargetInstance.CreationDate%"
$lfc.put()

And then to start everything off we connect the filter and consumer using an instance of the '__FilterToConsumerBinding' class. This class requires that you give it the unique identifiers of the filter and consumer that you want to connect. You can always get this from a WMI object by referencing its '__Path' property.

$FCBClass = [wmiclass]"\root\subscription:__FilterToConsumerBinding"
$fcb = $FCBClass.createinstance()
$fcb.Consumer = $lfc.__Path
$fcb.Filter = $ef.__Path
$fcb.put()

And that's it! WMI will now record every process that starts on your machine until you delete the binding.

But it doesn't work!

You may find that when you try to invoke the 'put' method on a WMI object you get an error like this

WMIError

If that happens just invoke 'Put' again (and again and again) and it will work - eventually!

 WMIWorking

You might also find that when you try to store the paths of your filter and consumer into the binding object you get nulls rather than  valid paths. Retrying a few times will fix this. I've seen this behaviour on XP and Vista. There's definitely something odd going on here but I haven't tracked it down yet.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:34 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Related posts

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

Saturday, July 05, 2008 4:39 AM