1

I've got an application which is watching over executed processes on a device using a managementeventwatcher, like so...

    Dim wmiq As String = "SELECT TargetInstance FROM __InstanceCreationEvent WITHIN  .025 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name like '%'"
    Dim scope As String = "\\.\root\CIMV2"
    startProcWatcher = New ManagementEventWatcher(scope, wmiq)
    AddHandler startProcWatcher.EventArrived, AddressOf ProcessStarted
    startProcWatcher.Start()

And my handler (just logging for now)...

  Private Shared Sub ProcessStarted(sender As Object, e As EventArrivedEventArgs)
    Dim targetinstance As ManagementBaseObject = e.NewEvent.Properties("TargetInstance").Value
    Dim processname As String = targetinstance.Properties("Name").Value.ToString
    Dim exepath As String = targetinstance.Properties("ExecutablePath").Value.ToString
    Dim thisexeinfo As New FileInfo(exepath)
    If Not ProcessExclusionList.Contains(processname) Then
        MyApp.DoLogging("Process Started : " & processname & "(" & exepath & ")")
    End If

End Sub

This works a treat and I successfully capture the event creation with minimal resource usage (as opposed to Process.GetProcesses(), which was hammering resource!), however I notice that if a second instance of the same process is run, I do not get an event on the second execution.

For example, I can run calculator and my watcher will log calc.exe was executed with all the associated properties. If I then open a second calculator my watcher sees nothing.

I'm guessing I need to modify the WMI query slightly, but my WMI is limited and I'm not struggling.

Can anyone help out with this?

TIA

John
  • 755
  • 1
  • 18
  • 46
  • The code you posted is missing the context of execution. Anyway, use [WqlEventQuery](https://learn.microsoft.com/en-us/dotnet/api/system.management.wqleventquery) to build your queries, not a string containing multiple settings. E.g., `dim scope = new ManagementScope("root\\CIMV2", [Options]) dim query = new WqlEventQuery("Win32_ProcessTrace") query.Condition = "ProcessName = 'calc.exe'" query.WithinInterval = new TimeSpan(0, 0, 0, 0, 250) dim startProcWatcher = new ManagementEventWatcher(scope, query)` – Jimi Feb 03 '22 at 13:27
  • See, e.g., [How do I get information about recently connected USB device?](https://stackoverflow.com/a/54298316/7444103) -- Of course you can write `query.Condition = "ProcessName LIKE '%calc%'"`, which should raise when either `win32Calc.exe` or `calc.exe` are run or terminated. -- Unrelated: the Event watcher **must** be stopped and any event handler removed before you initialize a new instance. This callback is quite *persistent*. – Jimi Feb 03 '22 at 13:38
  • @Jimi - scrap my question... its actually working perfectly, it just turns out that calculator only spawns one process no matter how many times you have it open, which totally confused me and led to me confusing you guys. every day is a school day.... – John Feb 03 '22 at 15:06

1 Answers1

0

The code I posted actually works perfectly for multiple instances of a process, however when I was testing, I used calc and it turns out calc spawns multiple instances of itself all under the same process.

repeating the test with any other executable/process results in the desired behavior.

John
  • 755
  • 1
  • 18
  • 46
  • If you change the code as shown in my first comment, you'll get an event each time a process is created, it doesn't matter whether the parent process (`win32calc`, in this case) associates the new Process to the main process, as it also happens in, e.g., Microsoft Office products. You'll also get an event when the child process is terminated, through the main Process (still `win32calc`, here). As described in the code I linked, you can check `__InstanceCreationEvent` or other type of events later. – Jimi Feb 03 '22 at 15:39