Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to monitor for the creation of specific processes.
Microsoft Scripting Guy, Ed Wilson, is here. This morning it is beginning to look like autumn. Who knows, it may become really hot and humid over the weekend, but today I can delude myself into hearing the rustling of leaves, imagine cool breezes blowing across the yard, and think of squirrels as they quickly gather supplies for a long winter.
All of these things are really quite simple, routine, and ordinary. And yet they demand a certain amount of preparation. If I don’t clean the leaf troughs in the early autumn, winter rains and subsequent freezing could spell disaster for the roof. If I don’t roll up hoses and bring them into the garage, pipes could freeze. If the squirrels don’t gather enough supplies for a long winter, they will be out scampering in the snow and risk untoward dangers.
And so it is with our computer systems—they demand monitoring, planning, and preparation for contingencies.
In yesterday’s post, Use PowerShell to Monitor for Process Startup, I talked about using the Register-CimIndicationEvent cmdlet to monitor for process startup. It worked well—maybe a bit too well because it triggers an event for every new process that starts. And in a modern operating system like Windows 8.1, there are all kinds of processes that start and stop all the time.
Today I want to use a query to modify the behavior of Register-CimIndicationEvent. To do this, I will use the Windows Management Instrumentation Query Language (WQL). Don’t worry. Because I am using the Win32_ProcessStartTrace WMI class, this will be really easy.
Note For more information about WMI event monitoring, see An Insider’s Guide to Using WMI Events and PowerShell.
Here are the steps I will take to permit me to monitor for the startup of a specific process:
- Open the Windows PowerShell console with elevated rights.
- Create a query that uses WQL syntax.
- Register to receive events by using the Register-CimIndicationEvent cmdlet and supplying the query.
- Use Get-Event to receive the events.
In addition, I will use the Get-EventSubscriber cmdlet to verify that the event was created properly, and I will use Remove-Event and Unregister-Event to perform cleanup.
Create the query
I first create the query. It looks pretty much like a SQL query. I select everything from the win32_ProcessStartTrace WMI class, and I limit the results to processes that are named Notepad.exe.
Note When I use Get-Process it tells me the ProcessName property is equal to notepad. But WMI expects the ProcessName property to be equal to notepad.exe. Keep in mind, no error generates if I use notepad, but I will not receive any events either.
I store my query string in a variable that I call $nq (for notepad query). Here is the query:
$nq = "Select * from win32_ProcessStartTrace where processname = 'notepad.exe'"
Register to receive events
Now I use the Register-CimIndicationEvent cmdlet to register to receive the events I defined in my query. I also specify a SourceIdentifier that I call nq. This makes it easy to receive only events generated by my specific notepad query. Here is the command:
Register-CimIndicationEvent -Query $nq -SourceIdentifier nq
Now I do a quick check. Did my registration work? I use Get-EventSubscriber. Are there any events? (There should not be at this point.) I use Get-Event.
Here is what my Windows PowerShell console looks like at this point:
Generate and receive events
Now I generate an event by launching Notepad. When I do that, I use the Get-Event cmdlet to receive the event. Here is the command:
Get-Event -SourceIdentifier nq
The returned object contains a number of properties. These properties are shown in the image that follows:
I know, from yesterday’s post, that the information I am interested in obtaining is contained in the SourceEventArgs property and in the NewEvent property under that. I use dotted notation to gain access to the important properties:
That was fun, do it again
That worked well. I can see that with the ProcessID I received, I could manage the newly created process if I needed to do so. But what about monitoring for an additional process? One way is to simply create another event registration. This time I will do it for Calc.exe. Here is the command:
$cq = "Select * from win32_ProcessStartTrace where processname = 'calc.exe'"
Register-CimIndicationEvent -Query $cq -SourceIdentifier cq
Now I launch Calculator (calc.exe) and retrieve the event. Here is the command that does that:
(Get-Event -SourceIdentifier cq).SourceEventArgs.newevent
This command and the output from the command are shown in the following image:
It still works with Notepad also. I simply use the nq source. I decide to clean up everything. Here are the commands I use:
get-event | Remove-Event
Get-EventSubscriber | Unregister-Event
Now there are no more events and no more event subscriptions.
A combined query
I can, of course, combine my two event queries into a single query. To do this, I use a compound where clause. Here is my new query (this is a single line query that wraps due to the length. It includes no returns or line continuation marks):
$q = "Select * from win32_ProcessStartTrace where processname = 'calc.exe' OR processname = 'notepad.exe'"
I register for events from this query just like I did for the other queries. Here is the command:
Register-CimIndicationEvent -Query $q -SourceIdentifier q
Now I launch both Notepad and Calculator, and I use Get-Event to retrieve my new events. Here is the command that does that:
(Get-Event -SourceIdentifier q).SourceEventArgs.newevent
The commands and their associated output are shown here:
That is all there is to using the Register-CimIndicationEvent cmdlet to monitor for a specific process. Join me tomorrow when I will talk about terminating a specific process when it starts up.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at email@example.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy