23

I have some services that an application needs running in order for some of the app's features to work. I would like to enable the option to only start the external Windows services to initialize after the application is launched. (as opposed to having them start automatically with the machine and take up memory when the application is not needed)

I do not have access to the exe's code to implement this, so ideally I would like to write a C# .Net Windows service that would monitor when an exe is launched.

What I've found so far is the System.IO.FileSystemEventHandler. This component only handles changed, created, deleted, and renamed event types. I don't expect that a file system component would be the ideal place to find what I'm looking for, but don't know where else to go.

Maybe I'm not searching with the right keywords, but I have not yet found anything extremely helpful on Google or here on stackoverflow.com.

The solution would be required to run on XP, Vista, and Win 7 when it comes...

Thanks in advance for any pointers.

  • Does this answer your question? [Is there a System event when processes are created?](https://stackoverflow.com/questions/972039/is-there-a-system-event-when-processes-are-created) – Mikael Dúi Bolinder Feb 20 '22 at 13:51

5 Answers5

39

From this article, you can use WMI (the System.Management namespace) in your service to watch for process start events.

 void WaitForProcess()
{
    ManagementEventWatcher startWatch = new ManagementEventWatcher(
      new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
    startWatch.EventArrived
                        += new EventArrivedEventHandler(startWatch_EventArrived);
    startWatch.Start();

    ManagementEventWatcher stopWatch = new ManagementEventWatcher(
      new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"));
    stopWatch.EventArrived
                        += new EventArrivedEventHandler(stopWatch_EventArrived);
    stopWatch.Start();
}

  static void stopWatch_EventArrived(object sender, EventArrivedEventArgs e) {
    stopWatch.Stop();
    Console.WriteLine("Process stopped: {0}"
                      , e.NewEvent.Properties["ProcessName"].Value);
  }

  static void startWatch_EventArrived(object sender, EventArrivedEventArgs e) {
    startWatch.Stop();
    Console.WriteLine("Process started: {0}"
                      , e.NewEvent.Properties["ProcessName"].Value);
  }
}

WMI allows for fairly sophisticated queries; you can modify the queries here to trigger your event handler only when your watched app launches, or on other criteria. Here's a quick introduction, from a C# perspective.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
  • 1
    Having some trouble executing this code on windows 7. I get an "access denied" error when calling startWatch.Start(). Has anyone found a workaroun for that? – tjjjohnson Feb 23 '10 at 19:35
  • 2
    @ tjjjohnson: Without looking into it, I suspect Windows 7 requires that watch to be run from an elevated process. Try using "Run as Administrator". – Michael Petrotta Feb 24 '10 at 00:56
  • 3
    +1 - Just a note... it seems that on the stop event, the ProcessName may be truncated. – Jim L Mar 07 '11 at 19:06
  • Awesome, Can we make WMI pool faster? i mean when i try to use this, there is always a lag in showing the created process name or destructed one. cant we just make this notification faster? – Hossein Jan 02 '14 at 04:57
5

you have 3 options here:

The reliable/intrusive one, set up a hook in unmanaged code that communicates back to your C# app whenever an app is launched. This is hard to get right and involves loading an extra DLL with each process. (Alternatively you could set up a driver, which is even harder to write)

The less reliable way, list all the processes (using the System.Diagnostics.Process class) on a regular basis (say every 10-30 secs) to see if the app is launched.

It also may be possible to watch the Win32_Process, InstanceCreationEvent WMI event from managed code. Not sure how reliable this is, but I suspect it would be better than polling processes.

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
0

In reply to the Windows 7 aspect of it not working. If you are monitoring 64 bit processes your process needs to be built to work in the 64bit address space too.

Jan S
  • 408
  • 6
  • 15
0
 public Process IsProcessOpen(string name)
        {
            foreach (Process clsProcess in Process.GetProcesses())
                if (clsProcess.ProcessName.Contains(name))
                    return clsProcess;
            return null;
        }
lankitha
  • 283
  • 7
  • 15
0

Monitor if the process is running - one service must be running to do this though.

If you really don't want to consume any ressources - write a simple service in plain C. Service application written without MFC/ATL can consume as low as 300-400 kb memory and virutally no CPU cycles. When the process you are interested in starts you can spawn your C# services.

devdimi
  • 2,432
  • 19
  • 18