Click here to Skip to main content
15,885,044 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
Context:
I'm trying to get a notification whenever a process starts so I can do some logging. So, I set up my event handler like this:

Process Information and Notifications using WMI[^]

actually, more like this:

http://weblogs.asp.net/whaggard/archive/2006/02/11/438006.aspx[^]

Pretty standard stuff.

This is for Windows XP and Windows 2000

The problem: Basically, my event handler sometimes dies mid-execution. This seems to happen when the process its event is referring to exits quickly.

For example, my event handler will run properly when I run netstat, but not when I run 'netstat -ano', which usually exits more quickly. In the latter case, the event handler will print out some of its output, but not all.

Sometimes, in the latter case, it won't print out anything, so I don't know if I got an event notification at all.

I have not found any mention of this problem in cyberspace. Maybe someone with better google-fu or better terminology can point me in the right direction.

Getting events Synchronously:

http://msdn.microsoft.com/en-us/library/aa720671(v=vs.71).aspx[^]

So, if I loop watcher.WaitForNextEvent();, I'll often get no event for a quick-exiting process. If I run netstat, I'll get a response like half the time.

Things I've tried:

I've tried subscribing to Win32_ProcessStartTrace and __InstanceCreationEvent/__InstanceOperationEvent, but the behavior is more-or-less the same.

I've tried implementing this in C++, but I get pretty much the same behavior: http://msdn.microsoft.com/en-us/library/windows/desktop/aa390425(v=vs.85).aspx[^]

I've mitigated the problem by making the event handler start a thread, but sometimes the event handler is not alive long enough to create a new thread (with all the data I'll need about the specified process).

Messing with the "WITHIN 1" clause in the query seems to have no effect. Removing it causes an error.





Incidentally:
The event handlers for process termination have all the time in the world. No race condition there.

I need to look at everything a process writes to stdout.

So, I need notification when the process starts so I can grab all the output of this process...unless one of you knows how to get everything a process already wrote to stdout from an __InstanceDeletionEvent or a Win32_ProcessStopTrace;

Thank You!
using System;
using System.Management;
using System.Threading;

// This example shows synchronous consumption of events. The client 
// is blocked while waiting for events. See additional example for
// asynchronous event handling.

public class EventWatcherPolling
{
    public static int Main(string[] args)
    {
        // Create event query to be notified within 1 second of 
        // a change in a service
        WqlEventQuery query =
           new WqlEventQuery("__InstanceCreationEvent",
                           new TimeSpan(0, 0, 1),
                         "TargetInstance isa \"Win32_Process\"");

        // Initialize an event watcher and subscribe to events 
        // that match this query
        ManagementEventWatcher watcher = new ManagementEventWatcher(query);

        while (true)
        {
            try
            {
                Console.WriteLine("Waiting:");
                // Block until the next event occurs 
                // Note: this can be done in a loop if waiting for 
                //        more than one occurrence
                ManagementBaseObject e = watcher.WaitForNextEvent();
                

                //Display information from the event
                Console.WriteLine(
                   "IC: {0}",
                    ((ManagementBaseObject)e["TargetInstance"])["Name"]);

            }
            catch (Exception except)
            {
                Console.WriteLine("EXCEPTION: " + except.ToString());
            }
        }

        //Cancel the subscription
        watcher.Stop();
        return 0;
    }
}
Posted
Updated 2-Apr-13 11:19am
v3
Comments
Dave Kreskowiak 2-Apr-13 16:56pm    
Your event handler just doesn't die on its own. The code continues to run, but what may be causing your problem is that the object you're looking at may die because it's lifetime is controlled by another source.

Without seeing you actual handler code, it's impossible to say.
The_Inventor 25-Aug-13 22:05pm    
Maybe some kind of while loop, where you load data until the condition become true.
Member 2036792 2-Apr-13 17:02pm    
THANK YOU FOR RESPONDING!

so, here's a simple synchronous example (just added a loop to this example: http://msdn.microsoft.com/en-us/library/aa720671(v=vs.71).aspx):

using System;
using System.Management;
using System.Threading;

// This example shows synchronous consumption of events. The client
// is blocked while waiting for events. See additional example for
// asynchronous event handling.

public class EventWatcherPolling
{
public static int Main(string[] args)
{
// Create event query to be notified within 1 second of
// a change in a service
WqlEventQuery query =
new WqlEventQuery("__InstanceCreationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_Process\"");

// Initialize an event watcher and subscribe to events
// that match this query
ManagementEventWatcher watcher = new ManagementEventWatcher(query);

while (true)
{
try
{
Console.WriteLine("Waiting:");
// Block until the next event occurs
// Note: this can be done in a loop if waiting for
// more than one occurrence
ManagementBaseObject e = watcher.WaitForNextEvent();


//Display information from the event
Console.WriteLine(
"IC: {0}",
((ManagementBaseObject)e["TargetInstance"])["Name"]);

}
catch (Exception except)
{
Console.WriteLine("EXCEPTION: " + except.ToString());
}
}

//Cancel the subscription
watcher.Stop();
return 0;
}
}


If you run ipconfig or netstat or stuff that returns quickly, this thing will only pick up some of the events.
Member 2036792 2-Apr-13 17:31pm    
You are right -- if I start my asynchronous handler like this:

static void startWatch_EventArrived(object sender, EventArrivedEventArgs e)
{
try
{
String name = (string)e.NewEvent.Properties["ProcessName"].Value;
Console.WriteLine("Process start handler {0}...", name);
Thread.Sleep(10000);
Console.WriteLine("...{0}", name);
...

It always makes it to the second console.writeline().

I'm the one who always kills my handler. That's very helpful! I wonder why my exception handler didn't tell me.

Anyway, this seems to have also solved my not-getting-any-event-at-all problem in the asynchronous example.

There still seems to be two problems.

1. The lingering race condition with resources: I still need to get some info from this event, and look up process info from it. Sometimes the process dies before I can do this. I could try to suspend the process -- but that would be a race condition, too.

2. synchronous example (my other comment post): I still have the not-getting-any-event-at-all problem in the synchronous example -- with quick-exiting processes.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900