2009-06-09 27 views
17

Tengo algunos servicios que necesita ejecutar una aplicación para que funcionen algunas de las características de la aplicación. Me gustaría habilitar la opción para iniciar solo los servicios externos de Windows para inicializar después de que se inicie la aplicación. (en lugar de hacer que se inicien automáticamente con la máquina y ocupar memoria cuando la aplicación no es necesaria)Monitor cuando se inicia un exe

No tengo acceso al código del exe para implementar esto, así que idealmente me gustaría escribir un C# .Net Servicio de Windows que supervisaría cuando se ejecuta un exe.

Lo que he encontrado hasta ahora es System.IO.FileSystemEventHandler. Este componente solo maneja tipos de eventos modificados, creados, eliminados y renombrados. No espero que un componente del sistema de archivos sea el lugar ideal para encontrar lo que estoy buscando, pero no sé a dónde más ir.

Tal vez no estoy buscando con las palabras clave correctas, pero todavía no he encontrado nada extremadamente útil en Google o aquí en stackoverflow.com.

La solución sería necesaria para funcionar en XP, Vista y Windows 7 cuando se trata ...

Gracias de antemano por cualquier punteros.

Respuesta

26

De this article, puede usar WMI (el espacio de nombre System.Management) en su servicio para ver los eventos de inicio del proceso.

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 permite consultas bastante sofisticadas; puede modificar las consultas aquí para activar su controlador de eventos solo cuando se inicia la aplicación que está mirando, o según otros criterios. Here's a quick introduction, desde una perspectiva de C#.

+0

Excelente respuesta. resolvió mi problema – Stimul8d

+0

Excelente, muy útil. ¡Aclamaciones! – tjjjohnson

+1

Tengo problemas para ejecutar este código en Windows 7. Aparece un error de "acceso denegado" al llamar a startWatch.Start(). ¿Alguien ha encontrado un workaroun para eso? – tjjjohnson

4

usted tiene 3 opciones aquí:

El fiable/intrusivo, preparar un gancho en el código no administrado que se comunica de nuevo a su aplicación de C# siempre que se inicie una aplicación. Esto es difícil de corregir e implica cargar una DLL adicional con cada proceso. (Alternativamente, podría configurar un controlador, que es aún más difícil de escribir)

La manera menos confiable, enumere todos los procesos (usando la clase System.Diagnostics.Process) regularmente (digamos cada 10-30 segundos) para ver si la aplicación se lanzó.

También es posible observar el evento Win32_Process, InstanceCreationEvent WMI desde el código administrado. No estoy seguro de cuán confiable es esto, pero sospecho que sería mejor que los procesos de votación.

0

Controle si el proceso se está ejecutando; sin embargo, se debe ejecutar un servicio para hacerlo.

Si realmente no desea consumir ningún recurso, escriba un servicio simple en C. La aplicación de servicio escrita sin MFC/ATL puede consumir tan poca memoria de 300-400 kb y virutalmente no hay ciclos de CPU. Cuando comienza el proceso que le interesa, puede generar sus servicios de C#.

0
public Process IsProcessOpen(string name) 
     { 
      foreach (Process clsProcess in Process.GetProcesses()) 
       if (clsProcess.ProcessName.Contains(name)) 
        return clsProcess; 
      return null; 
     } 
0

En respuesta al aspecto de Windows 7 no funciona. Si está supervisando procesos de 64 bits, su proceso debe ser desarrollado para que funcione también en el espacio de direcciones de 64 bits.

Cuestiones relacionadas