Pull to refresh

Работа с WMI. События для процессов

Reading time4 min
Views8.1K
Мониторить список процессов можно разными способами, мне понравился вариант с использованием WMI, с помощью которого, мы можем обработать событие создание процесса, изменения, удаления и т.п.


Мы создадим свой промежуточный класс для работы

using System;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
using System.Management; //для всего нам понадобится подключить пространство имен Management

namespace WMI.Win32
{
  public delegate void ProcessEventHandler(Win32_Process proc);

  public class ProcessWatcher: ManagementEventWatcher
  {
    // События процесса
    public event ProcessEventHandler ProcessCreated;
    public event ProcessEventHandler ProcessDeleted;
    public event ProcessEventHandler ProcessModified;

   // WMI WQL запросы
   static readonly string WMI_OPER_EVENT_QUERY = @«SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'»; // запрос на получения списка всех процессов
   static readonly string WMI_OPER_EVENT_QUERY_WITH_PROC = WMI_OPER_EVENT_QUERY + « and TargetInstance.Name = '{0}'»; // запрос на получение конкретного процесса по имени запущеного .exe файла

   public ProcessWatcher()
   {
     Init(string.Empty);
   }

   public ProcessWatcher(string processName)
   {
     Init(processName);
   }
   private void Init(string processName)
   {
     this.Query.QueryLanguage = «WQL»;
     if (string.IsNullOrEmpty(processName))
     {
       this.Query.QueryString = WMI_OPER_EVENT_QUERY;
     }
     else
     {
       this.Query.QueryString =
       string.Format(WMI_OPER_EVENT_QUERY_WITH_PROC, processName);
     }

     this.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
   }

   private void watcher_EventArrived(object sender, EventArrivedEventArgs e)
   {
     string eventType = e.NewEvent.ClassPath.ClassName;
     Win32_Process proc = new
     Win32_Process(e.NewEvent[«TargetInstance»] as ManagementBaseObject);

     // определяем какое событие произошло
     switch (eventType)
     {
       case "__InstanceCreationEvent":
         if (ProcessCreated != null)
           ProcessCreated(proc);
         break;
       case "__InstanceDeletionEvent":
         if (ProcessDeleted != null)
           ProcessDeleted(proc);
         break;
       case "__InstanceModificationEvent":
         if (ProcessModified != null)
           ProcessModified(proc); break;
     }
   }
  }
}

Как этим пользоваться?

class Program
{
   static void Main(string[] args)
   {
     ProcessWatcher procWatcher = new ProcessWatcher(«notepad.exe»); // отследиваем действия по блокнотам
     procWatcher.ProcessCreated += new ProcessEventHandler(procWatcher_ProcessCreated);
     procWatcher.ProcessDeleted += new ProcessEventHandler(procWatcher_ProcessDeleted);
     procWatcher.ProcessModified += new ProcessEventHandler(procWatcher_ProcessModified);
     procWatcher.Start();
     while (true)
     {
       procWatcher.WaitForNextEvent(); //ожидаем следующее событие
     }

     procWatcher.Stop(); // да по логике этот код не достижим, но вдруг нам нужно будет перестать следить за событиями
   }

   static void procWatcher_ProcessCreated(Win32_Process process)
   {
     Console.Write("\nCreated\n "+ process.Name +" "+ process.ProcessId);
   }

   static void procWatcher_ProcessDeleted(Win32_Process proc)
   {
     Console.Write("\nDeleted\n");
   }

   static void procWatcher_ProcessModified(Win32_Process proc)
   {
     Console.Write("\nModified\n");
   }
}



Вы наверное заметили, что наш класс ProcessWatcher использует Win32_Process, которого нет в .NET Framework, для его генерации и вообще если вам нужно вплотную работать с WMI, Майкрософт(ай молодцы), дали нам утиль — mgmtclassgen, которая сгенерит строготипизированый класс для любой WMI таблицы.
Для этого запускаем консоль студии, набираем mgmtclassgen Win32_Process /n root\cimv2 /P Win32_Process.cs
Видим
Microsoft Management Strongly Typed Class Generator Version
1.1.4322.573
Copyright c Microsoft Corporation 1998-2002. All rights reserved.
Generating Code for WMI Class Win32_Process…
Code Generated Successfully!!!

И радуемся теперь мы можем забрать наш готовый класс из «C:\Program Files\Microsoft Visual Studio 9.0\VC» (2008) студии.
Если нужно сгенерировать класс на разных языках добавляем параметр /l VB, в данном случае vb.net класс готов.
Стоит только заметить, что нужно просто заменить в сгенереном файле названия класса на Win32_Process(везде где оно используется), что бы не путать с System.Diagnostics.Process.

Теперь осталось запустить нашу программу, далее запустить блокнот и вуаля.

P.S. Я был легко шокирован, когда увидел, что в сгенерином классе Win32_Process был послность русский коментарий!
Tags:
Hubs:
Total votes 29: ↑24 and ↓5+19
Comments12

Articles