Question Process started/terminated event?

DragonQ

Member
Joined
Nov 2, 2008
Messages
9
Programming Experience
Beginner
Hi all,

Originally I was using Process.GetProcesses in a timer that runs every 50ms to check for when a new process of a certain name was started. However, not only does this result in applications that start up quickly displaying for a short time, but also the application takes up to 5% CPU time which is way too high.

So, is it possible to hook onto some event that lets you know when a process has been started or terminated? I found a few code examples on the internet in C# that use "WMI" but they all seem to use what is effectively a timer so this doesn't help with either problem. :(


Thanks,

DragonQ.
 
Yeah I found that one first but I cannot convert it properly because I don't understand what these lines are supposed to contain:

VB.NET:
    ' Auto-Generated running: mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32
    ' Renaming the class from Process to Win32_Process
    Public Class Win32_Process
		Private ... 
    End Class

Which means that the following line doesn't work:

VB.NET:
Dim proc As New Win32_Process(TryCast(e.NewEvent("TargetInstance"), ManagementBaseObject))


Also, it does use a timer. Notice the query string:

VB.NET:
Private Shared ReadOnly WMI_OPER_EVENT_QUERY As String = "SELECT * FROM " & ControlChars.CrLf & "__InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"

The "WITHIN 1" means it queries once per second. I know this because the system I'm using now uses the same query method. :/
 
The "WITHIN 1" means it queries once per second. I know this because the system I'm using now uses the same query method. :/
I wasn't aware.
 
Yeah I didn't think it used a timer at first either ;). I managed to find a way to not use a timer, which reduces the CPU usage to essentially 0%. However, the delay between a process starting and the event being called is too big. It can take up to a second! :(

Here's the code I'm using at the moment (on a separate thread to the main code):

VB.NET:
    Public Sub WatchForNewProcesses()
        Try
            Dim query As New WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace")
            Dim watcher As New ManagementEventWatcher(query)
            Dim eventObj As ManagementBaseObject = watcher.WaitForNextEvent()

            watcher.Stop()
            ProcessStarted(Me)
        Catch ex As ManagementException
            Debug.WriteLine("An error occurred while trying to receive an event: " & ex.Message)
        End Try
    End Sub

Any ideas as to why the response of watcher.WaitForNextEvent() is so slow? :confused: The only other thing the program is doing whilst this is all happening is handling events for System.IO.FileSystemWatcher(). However, taking this out does not improve the response time of the process watcher.
 
I checked out this page:

ManagementEventWatcher.WaitForNextEvent Method (System.Management)

The simple "usage" at the top doesn't work:

VB.NET:
        Dim instance As ManagementEventWatcher
        Dim returnValue As ManagementBaseObject

        returnValue = instance.WaitForNextEvent()
        Return returnValue

because "instance" doesn't equal anything. If I place a "new" after "Dim instance As" then I just get an "unparsable query" error (presumably because there's no query given to "instance"). If I then put in a query, I end up with the equivalent of the code I already have:

VB.NET:
            Dim query As New WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace")
            Dim watcher As New ManagementEventWatcher(query)
            Dim eventObj As ManagementBaseObject = watcher.WaitForNextEvent()

The more complex code at the bottom of the MSDN page is another polling/timer based system and useless to me. Did you mean something different by "MSDN documentation"?
 
Ah, I think I see what you mean! I'm now using this code and it works perfectly (0% CPU usage until a process starts and the process exits very quickly):

VB.NET:
            Dim WQLEventQuery As New WqlEventQuery("__InstanceCreationEvent", New TimeSpan(0, 0, 0, 0, 10), "TargetInstance isa ""Win32_Process""")
            Dim Watcher As New ManagementEventWatcher(WQLEventQuery)

            Dim EventObject As ManagementBaseObject = Watcher.WaitForNextEvent()

            Watcher.Stop()
            ProcessStarted(Me)

The only problem I have is that if you select the "bad" file and hold down Enter to open 50 or whatever windows, they all get closed instantly except the last one or two which for some reason stay open. However, I doubt this is a problem with the code above, it's probably to do with how I'm implementing it. I thought of trying to delete the file that started the process but I don't think this is possible unfortunately. :confused:

I'll try to see if I can find why some windows stay open when you hold enter...if I can't, I'll ask for more help! :D
 
Yeah I found that one first but I cannot convert it properly because I don't understand what these lines are supposed to contain:

VB.NET:
    ' Auto-Generated running: mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32
    ' Renaming the class from Process to Win32_Process
    Public Class Win32_Process
		Private ... 
    End Class


Look at the comment. It means open a dos window and run this:
mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32

Then rename the resulting class from Process to Win32_Process
 
Back
Top