Create WMI event subscriptions to monitor your folders
- select the contributor at the end of the page -
What is a WMI event subscription?
A WMI event subscription is a method of subscribing to certain WMI events. WMI events are constantly being fired inside the WMI repository, based on a number of various activities. WMI has various classes inside the repository. Some of these classes are called event classes. Event classes do not necessarily contain static data like many other classes. Instead, they simply report on a specific type of activity. For example, in our scenario, I want to know when a file is placed into a folder. To do this, I'd subscribe to the __InstanceCreationEvent
event class and use a target instance of the CIM_DataFile
class. This would enable me to see all files being moved around the computer.
There are two types of WMI event subscriptions: temporary and permanent. If created with PowerShell, temporary event subscriptions are removed as soon as the PowerShell console is closed. They are nice for testing, but they don't work well for actual production scripts. This is why you'll need to create permanent subscriptions. These subscriptions get stored in the WMI repository and aren't dependent on PowerShell at all. They still work when the PowerShell console is closed or the PC is rebooted. For this reason, we'll concentrate on permanent event subscriptions in this article.
A WMI event subscription consists of three parts: the filter, the consumer, and the binding. Let's look at these parts in detail.
The filter
The WMI filter is a WQL query represented by the __EventFilter
WMI class. This piece of the subscription is used to narrow down what's being returned by the event class. I've already mentioned the CIM_DataFile
class. If I were to subscribe to this class, I'd get all instances of all files being moved around the computer. I only want to monitor a single folder, so I would apply a filter that only looks for files being added to that folder. The filter is also where you specify the frequency of polling. Unlike scheduled tasks, polling can be specified down to the second!
The consumer
The next piece of a subscription is the consumer. The consumer instructs the subscription on what to do when an event is caught. In our example, the consumer is called the ActiveScriptEventConsumer
object. This is the object that is created, which specifies the script that will execute when the event we're looking for fires.
The binding
Finally, we need the binding. This is another object that essentially binds the consumer and the filter together. It is represented by the __FilterToConsumerBindingClass
WMI class. The binding is a necessary piece in the overall subscription. It essentially enables the consumer to execute our script.
I've created a PowerShell module called FileMonitor that enables you to easily create a permanent WMI event consumer that monitors for file creation. FileMonitor has three functions: New-FileMonitor
, Remove-FileMonitor
, and Get-FileMonitor
. Using these functions, you can create and manipulate your various WMI subscriptions without having to worry about all the obscure code required to manage them.
For example, let's say I want to monitor the folder C:\MyFolder
every 10 seconds for any files. If a file shows up, I want this recorded into the log file C:\MyLogFile.log
. To do this, I will create a PowerShell script that will add this information into C:\MyLogFile.log
when a file is dropped into the C:\MyFolder
folder.
The FileMonitor module only creates and manages the permanent event consumer. Therefore, it's up to you to create a couple of scripts with the actions you want taken after a file goes into the MyFolder
folder. First, you'll want to create a VBScript script in the root of the C:
directory called callps1.vbs
. Unfortunately, it's not possible to call a PowerShell script directly from an event consumer, so we're forced to use an old-school VBScript script as a relay to a PowerShell script.
I have this in my C:\callps1.vbs
script.
objShell.run("powershell.exe -WindowStyle Hidden -executionpolicy bypass -file ""C:\callfromvbs.ps1""")Set objShell = CreateObject("Wscript.shell")
I'm simply using this VBScript script to launch the PowerShell script C:\callfromvbs.ps1
. Next, create the callfromvbs.ps1
script and add a single line.
Add-Content -Path 'C:\MyLogFile.log' -Value 'A file was found in the C:\MyFolder folder.'
This dead-simple script simply adds a line into the C:\MyLogFile.log
file with the text "A file was found in the C:\MyFolder folder."
Now that we've got the VBScript relay script and the PowerShell script that we'd like to run, it's just a matter of creating the permanent WMI event consumer with the New-FileMonitor
cmdlet!
New-FileMonitor -Name 'MyMonitor' -MonitorInterval 10 -FolderPath 'C:\MyFolder' -ScriptFilePath C:\callps1.vbs
Run this, and if you want to make sure it was created, run Get-FileMonitor
shortly afterward. You should now see the file monitor that you just created. This means you've successfully created your first permanent WMI event consumer to monitor files! Test it out by placing any file in the C:\MyFolder
folder. Notice how the C:\MyLogFile.log
file is created and contains a single line.
Permanent WMI event consumers can do so much more than just monitoring for files. I challenge you to get acquainted with WMI event consumers and see what else you can come up with.