2009-05-11 3 views
20

특정 파일 이름의 실행 파일이 시작될 때 발생하는 이벤트에 등록하는 방법이 있습니까? 프로세스가 종료 될 때 프로세스를 처리하고 종료 된 이벤트를 등록함으로써 이벤트를 얻는 것이 쉽다는 것을 알고 있습니다. 그러나 이미 실행중인 프로세스가 실행중인 모든 프로세스를 폴링하지 않고 시작할 때 어떻게 알림을받을 수 있습니까?.NET 이벤트에 대한 프로세스 실행 시작

답변

30

는 다음을 사용할 수

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

당신은 다음 (예 : "NOTEPAD.EXE")을 사용자의 프로세스 이름을 전달 WatchForProcessStart 및/또는 WatchForProcessEnd 중 하나를 부를 것이다.

ManagementEventWatcher 개체는 IDisposable을 구현하므로 두 Watch * 메서드에서 반환되므로 문제를 방지하기 위해 끝낼 때 이러한 개체에 Dispose를 호출해야합니다.

프로세스 시작 후 이벤트가 더 빨리 발생해야하는 경우에도 쿼리의 폴링 값을 변경할 수 있습니다. 이렇게하려면 "WITHIN 10"줄을 10보다 작게 변경하십시오.

+0

이 코드는 리팩토링 될 수 있지만 이해를 돕기 위해 자세한 내용을 남겨 두었습니다 – Clive

+1

이제 답변입니다! 감사! –

+0

실제로이 코드는 잘 보입니다. 그러나 그것은 나를 위해 작동하지 않습니다. 나는 어떤 점도 놓치고있다? win7, net 2.o 프로젝트. – Yaya

3

WMI는 프로세스가 만들어 질 때 이벤트를 만들 수 있습니다. 그런 다음 이러한 이벤트를 필터링 할 수 있습니다.

+1

예제가 좋을 것입니다. –

+0

@Adam : 나는 그 의견을 기다리고있었습니다. 안타깝게도 WMI 이벤트 (수년간)에서 작업 한 이후로 .NET을 사용하지 않았으므로 오랜 시간이 걸렸습니다. 따라서이 작업을 직접 수행하는 방법을 배워야하고 현재로서는 시간이 없습니다. – Richard

1

여기에 코드가 있습니다.

이 코드를 실행하려면 Administrator와 같은 Visual Studio를 시작해야합니다.

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); 
      } 
     } 
    } 
} 
관련 문제