2009-05-11 9 views
20

Czy istnieje sposób rejestracji zdarzenia, które zostanie wywołane po uruchomieniu pliku wykonywalnego o określonej nazwie? Wiem, że łatwo jest uzyskać zdarzenie, gdy proces się kończy, przez uzyskanie obsługi procesu i zarejestrowanie się na zdarzenie zakończone. Ale jak możesz zostać powiadomiony, kiedy proces, który jeszcze nie działa, zaczyna się ... bez odpytywania wszystkich uruchomionych procesów?. Zdarzenia .NET do uruchomienia pliku uruchamialnego

Odpowiedz

30

Można użyć następujących:

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)); 
    } 

Będziesz wtedy zadzwonić albo WatchForProcessStart i/lub WatchForProcessEnd przekazując swoją nazwę procesu (np "notepad.exe").

Obiekt ManagementEventWatcher jest zwracany z dwóch metod Watch *, ponieważ implementuje IDisposable, więc powinieneś wywołać Dispose na tych obiektach, gdy skończyłeś z nimi, aby zapobiec problemom.

Możesz również zmienić wartość pollingu w zapytaniach, jeśli chcesz, aby zdarzenie zostało podniesione szybciej po rozpoczęciu procesu. Aby to zrobić, zmień wiersz "WITHIN 10" na WIĘCEJ mniej niż 10.

+0

Ten kod mógł zostać refaktoryzowany, ale pozostawiłem go pełnym gadżetem, aby pomóc w zrozumieniu – Clive

+1

Teraz to jest odpowiedź! Dzięki! –

+0

faktycznie ten kod wygląda dobrze. Ale to nie działa dla mnie. Brakuje mi jakiegoś punktu? win7, net 2.o project. – Yaya

3

Usługa WMI może tworzyć zdarzenia po utworzeniu procesów. Możesz wtedy filtrować te zdarzenia.

+1

Przykład byłby miły :) –

+0

@Adam: Spodziewałem się tego komentarza. Niestety minęło trochę czasu odkąd pracowałem z wydarzeniami WMI (lata), a nie z .NET, więc musiałbym nauczyć się jak to zrobić sam ... i nie mam czasu w tej chwili. – Richard

1

Oto kod.

Należy zauważyć, że aby uruchomić ten kod, należy uruchomić program Visual Studio, taki jak Administrator.

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); 
      } 
     } 
    } 
} 
Powiązane problemy