6

My application need to wait until specific process will be started. I am doing it this way

while (Process.GetProcessesByName("someProcess").Length == 0)
{
    Thread.Sleep(100);
}

Is there any other way(more elegant) how to accomplish this, with functionality similar to WaitForExit()? Thanks for answers.

sanjuro
  • 1,611
  • 1
  • 21
  • 29
  • WaitForInputIdle (http://msdn.microsoft.com/en-us/library/8d7363e2.aspx) will let you know when an message pumping application is idle. This could be used to see when a process is finished loading, but I guess you don't even know if it is started loading. – Lars Truijens Jul 04 '11 at 19:30
  • possible duplicate of [Look Up for new process started using c#](http://stackoverflow.com/questions/3455092/look-up-for-new-process-started-using-c) – Hans Passant Jul 04 '11 at 19:30

2 Answers2

8

Take a look at the ManagementEventWatcher class.

Specifically, the code example at the bottom of the link shows you how to setup a ManagementEventWatcher to be notified when a new process is created.

Code copied from MSDN code example (could stand a little cleanup):

using System;
using System.Management;

// This example shows synchronous consumption of events. 
// The client is blocked while waiting for events. 

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();
        watcher.Query = query;
        // times out watcher.WaitForNextEvent in 5 seconds
        watcher.Options.Timeout = new TimeSpan(0,0,5);

        // Block until the next event occurs 
        // Note: this can be done in a loop if waiting for 
        //        more than one occurrence
        Console.WriteLine(
            "Open an application (notepad.exe) to trigger an event.");
        ManagementBaseObject e = watcher.WaitForNextEvent();

        //Display information from the event
        Console.WriteLine(
            "Process {0} has been created, path is: {1}", 
            ((ManagementBaseObject)e
            ["TargetInstance"])["Name"],
            ((ManagementBaseObject)e
            ["TargetInstance"])["ExecutablePath"]);

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

Edit

Simplifed example with TargetInstance.Name = 'someProcess' filter added.

  var query = new WqlEventQuery(
                "__InstanceCreationEvent", 
                new TimeSpan(0, 0, 1), 
                "TargetInstance isa \"Win32_Process\" and TargetInstance.Name = 'someProcess'"
              );

  using(var watcher = new ManagementEventWatcher(query))
  {
    ManagementBaseObject e = watcher.WaitForNextEvent();

    //someProcess created.

    watcher.Stop();
  }
Chris Baxter
  • 16,083
  • 9
  • 51
  • 72
  • thanks for answer and which approach is better(more convenient to cpu), using ManagementEventWatcher or actively waiting like in my piece of code? thanks – sanjuro Jul 04 '11 at 20:03
  • @sanjuro - WMI is the recommended approach; polling the process list in C# is an expensive operation. I do not have explicit stats available for review; but if you are truly concerned you can always run some comparisons locally (that being said, I would only worry about it if this is deemed to be a performance bottleneck). – Chris Baxter Jul 04 '11 at 20:45
2

As far as I know, there is nothing on the Process class that will make it simple.

If you don't have control over the source code in the sub-process, then you should probably go with the WMI solution that Calgary Coder provided.

If you do have control of the code in the sub-process, then there are a few additional ways you can solve this problem. I have used WCF (using an IPC binding), .Net Remoting, and Mutex.

The advantage of these solutions is that the sub process has to opt into it. The sub process is free to wait until it has completed its startup initialization routines before letting the parent app know that it is "ready".

There are samples at each of those links that should give you a start on solving this problem. If you are interested in going with a specific one, and have problems, let me know and I'll post some sample code for that particular solution.

Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183