2009-05-11 11 views
20

¿Hay alguna forma de registrarse para un evento que se dispara cuando se inicia un ejecutable de un nombre de archivo particular? Sé que es bastante fácil obtener un evento cuando sale un proceso, haciendo que el proceso se maneje y se registre para el evento salido. Pero, ¿cómo se le puede avisar cuando un proceso, que aún no se está ejecutando, comience ... sin interrogar todos los procesos en ejecución?.NET Eventos para el ejecutable de proceso start

Respuesta

30

podría utilizar el siguiente:

private ManagementEventWatcher WatchForProcessStart(string processName) 
    { 
     string queryString = 
      "SELECT TargetInstance" + 
      " FROM __InstanceCreationEvent " + 
      "WITHIN 10 " + 
      " WHERE TargetInstance ISA 'Win32_Process' " + 
      " AND TargetInstance.Name = '" + processName + "'"; 

     // The dot in the scope means use the current machine 
     string scope = @"\\.\root\CIMV2"; 

     // Create a watcher and listen for events 
     ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString); 
     watcher.EventArrived += ProcessStarted; 
     watcher.Start(); 
     return watcher; 
    } 

    private ManagementEventWatcher WatchForProcessEnd(string processName) 
    { 
     string queryString = 
      "SELECT TargetInstance" + 
      " FROM __InstanceDeletionEvent " + 
      "WITHIN 10 " + 
      " WHERE TargetInstance ISA 'Win32_Process' " + 
      " AND TargetInstance.Name = '" + processName + "'"; 

     // The dot in the scope means use the current machine 
     string scope = @"\\.\root\CIMV2"; 

     // Create a watcher and listen for events 
     ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString); 
     watcher.EventArrived += ProcessEnded; 
     watcher.Start(); 
     return watcher; 
    } 

    private void ProcessEnded(object sender, EventArrivedEventArgs e) 
    { 
     ManagementBaseObject targetInstance = (ManagementBaseObject) e.NewEvent.Properties["TargetInstance"].Value; 
     string processName = targetInstance.Properties["Name"].Value.ToString(); 
     Console.WriteLine(String.Format("{0} process ended", processName)); 
    } 

    private void ProcessStarted(object sender, EventArrivedEventArgs e) 
    { 
     ManagementBaseObject targetInstance = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value; 
     string processName = targetInstance.Properties["Name"].Value.ToString(); 
     Console.WriteLine(String.Format("{0} process started", processName)); 
    } 

A continuación, llamar a cualquiera WatchForProcessStart y/o WatchForProcessEnd que pasa en su nombre de proceso (por ejemplo, "notepad.exe").

El objeto ManagementEventWatcher se devuelve desde los dos métodos Watch * mientras implementa IDisposable, por lo que debe llamar a Dispose en estos objetos cuando haya terminado con ellos para evitar problemas.

También puede cambiar el valor de sondeo en las consultas si necesita que el evento se eleve más rápidamente después de que el proceso haya comenzado. Para hacer esto, cambie la línea "DENTRO DE 10" para estar dentro de algo menor que 10.

+0

Este código podría ser refactorizado, pero lo dejé prolijo para ayudar a comprender – Clive

+1

Ahora ¡ESO es una respuesta! ¡Gracias! –

+0

en realidad este código se ve bien. Pero no funciona para mí. Me falta algo? win7, proyecto de red 2.o. – Yaya

3

WMI puede crear eventos cuando se crean procesos. A continuación, puede filtrar estos eventos.

+1

Un ejemplo sería bueno :) –

+0

@ Adam: esperaba ese comentario. Desafortunadamente ha pasado un tiempo desde que trabajé con eventos de WMI (años), y no con .NET, así que tendría que aprender a hacerlo yo mismo ... y no tengo tiempo en este momento. – Richard

1

Aquí está el código.

Observe que debe iniciar Visual Studio como administrador para ejecutar este código.

using System; 
using System.Management; 

namespace AppLaunchDetector 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     {   
      ManagementEventWatcher w = null; 
      WqlEventQuery q; 
      try 
      { 
       q = new WqlEventQuery(); 
       q.EventClassName = "Win32_ProcessStartTrace"; 
       w = new ManagementEventWatcher(q); 
       w.EventArrived += new EventArrivedEventHandler(ProcessStartEventArrived); 
       w.Start(); 
       Console.ReadLine(); // block main thread for test purposes 
      } 
      catch (Exception ex) 
      { 

      } 
      finally 
      { 
       w.Stop(); 
      } 
     } 

     static void ProcessStartEventArrived(object sender, EventArrivedEventArgs e) 
     { 
      foreach (PropertyData pd in e.NewEvent.Properties) 
      { 
       Console.WriteLine("\n============================= ========="); 
       Console.WriteLine("{0},{1},{2}", pd.Name, pd.Type, pd.Value); 
      } 
     } 
    } 
} 
Cuestiones relacionadas