Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to terminate processes that start at random times.
Hey, Scripting Guy! I have a question that I hope you can answer. It seems that there are several processes that keep starting on my computer running Windows 8.1. That eat up lots of resources, and I cannot seem to find where they are coming from. I have used the Sysinternals autoruns command, and yet they keep coming and consuming. What I would really love is to have a script that detects when these bogus processes start, and then terminate them. Can you help with that?
—CF
Hello CF,
Microsoft Scripting Guy, Ed Wilson, is here. This morning it is Friday. WooHoo, the weekend baby! Actually, my weekends are pretty much like my weekdays, so I am not really one of those people who lives for the weekend. Having said that, it is still nice to have a weekend once in a while.
So I am sitting on the porch, sipping a cup of English Breakfast tea with a cinnamon stick and a bit of lemon grass in it. I am checking my email at scripter@microsoft.com, and I ran across your email. The answer is, "Yes, I can write a bit of Windows PowerShell script that will detect when a specific process starts, and once that process starts, I can terminate that specific process." The technique is amazingly simple with Windows PowerShell. (Using VBScript in the old days, this was a bit of a bear.)
Detecting a process and terminating it
There are three steps required to detect when a specific process starts and then terminate the process:
- Write a WQL query that uses the Win32_ProcessStartTrace WMI class with a filter for a specific process.
- Register to receive events by using the Register-CimIndicationEvent Windows PowerShell cmdlet. In the command, use the query and specify an action to stop the process.
- Use the Wait-Event cmdlet to wait until an event triggers the action.
Note Today's blog post builds on concepts that I discussed yesterday in Use PowerShell to Monitor Specific Process Creation, so you should review that post first.
To work properly, the Windows PowerShell console must launch with Admin rights. Right-click the Windows PowerShell console icon, and select “Run As Administrator.”
Develop the query
To develop my query, I use WMI Query Language (WQL) and I query the Win32_ProcessStartTrace WMI class. This class is designed especially to detect when a new process begins, and therefore, it is easy to use. I use the Where clause to specify the ProcessName I want to detect. This requires that I specify the program file extension (unlike Get-Process, which only uses the base name). Here is the query I use:
$Q = "Select * from win32_ProcessStartTrace where processname = 'notepad.exe'"
Register for events
Now I want to register for events. In addition, I want to specify an action—that is, I want to stop the process when it launches. To do this, I will use an automatic variable, $event, that is generated when an event occurs. I use the $event variable to drill into the object. I go into SourceEventArgs, grab the NewEvent property and select the ProcessID. This is the program PID, and I pass it to the Stop-Process cmdlet. When a new instance of Notepad launches, within a short period of time, it is terminated. Here is the script:
Register-CimIndicationEvent -Query $q -SourceIdentifier Q -Action {Stop-Process $event.SourceEventArgs.newevent.processID}
Wait for it…
Now I need to wait for an event to arise. To do this, I use the Wait-Event cmdlet. This cmdlet pauses the Windows PowerShell console and waits for events to arise. When I no longer want this to happen, I use Ctrl-C to break out of the wait cycle. Nothing appears on the screen while it is waiting or when a process terminates. The Windows PowerShell console is shown here:
When I break the Wait-Event cycle, Windows PowerShell no longer terminates the process. But if I start up again, Wait-Event (prior to removing the subscription) will continue to work. When I close Windows PowerShell, everything is reset to defaults.
CF, that is all there is to using Windows PowerShell to terminate processes that keep starting. Join me tomorrow when we will have another great guest blog post by Windows PowerShell MVP, Sean Kearney.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy