Using WMI to monitor process creation, deletion and modification in .NET

WMI is a powerful tool and I have just recently discovered some of its power. Previously I though the only way to detect process creation was by creating a windows hook but now I know it is fairly simple to due with .NET using the Windows.Management namespace. Below is simple ProcessWatcher class that has events that are triggered when a process is created, deleted or modified. Enjoy!

using System;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
using System.Management;

namespace WMI.Win32
{
    public delegate void ProcessEventHandler(Win32_Process proc);
    public class ProcessWatcher : ManagementEventWatcher
    {
        // Process Events
        public event ProcessEventHandler ProcessCreated;
        public event ProcessEventHandler ProcessDeleted;
        public event ProcessEventHandler ProcessModified;

        // WMI WQL process query strings
        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}'";

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

    // Auto-Generated running: mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32
    // Renaming the class from Process to Win32_Process
    public class Win32_Process { ... }
}

// Sample Usage
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();

// Do Work

procWatcher.Stop();

24 Comments

  • Got this error "No overload for method 'Win32_Process' takes '1' arguments" for the following code:



    Win32_Process proc = new Win32_Process(e.NewEvent["TargetInstance"] as ManagementBaseObject);

  • Never mind. I had the wrong name space!

  • I can not find a definition for Win32_Process class.

  • You need to generate by running: mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32
    and then renaming the class Process to Win32_Process.

  • Nice article!
    Informative and useful..

  • Alex - I don't believe you can use WMI to monitor folder browsing (at least not that I know of). Monitoring folder browsing is really a shell thing, so perhaps you could write a shell extension to do it.

  • This is a really nice article and seems to do what i need, but I can't seem to get the code working. I generate the code into EventWatchTest namespace as a test, but I seem to just get the error mentioned above:
    Got this error "No overload for method 'Win32_Process' takes '1' arguments" for the following code. Also the processCreated event handlers declaration bit doesn't seem to work? Any ideas?

  • Since you changed the namespace that this code lives in you need to access Win32_Process via it's entire name (i.e. WMI.Win32.Win32_Process) or just include using WMI.Win32.

  • I was wondering if you've noticed any massive CPU usage using this?

    I'm developing a WLM Addin which monitors when games run/close and set the status accordingly.
    Unfortunately, each game thats detected to be installed requires about 5% CPU usage...with 10games installed, half my CPU power is drained!

  • how do u mean auto generated Win32_Process class?
    and where to put script "mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32" in order to autogenerate? please explain me

  • Civa - You only need to run "mgmtclassgen Win32_Process /n root\cimv2 /o WMI.Win32" once to generate the class you don't need to generate it every build. I believe you should be able to run it from the VS command prompt.

  • I created a C# project in my solution for ProcessWatcher and I am trying to add access it via VB.NET. I am trying to add a handler to the ProcessWatcher events in VB and am getting an error when I create my delegate that the Win32.Win32_Process is not CLS compliant. Any ideas on how to fix it?

  • That is a really well designed class and highly useful. Thanks for sharing.

    Yours,
    Alois Kraus

  • What' if I created the process using WMI on remote host and want to monitor the created process on the remote machine? is there any way to make this process watcher class point to remote process?

  • The name 'procWatcher_ProcessCreated' does not exist in the current context, am getting this error can anyone help me figure out what's going on?

  • I tried to convert this to VB.NET and I'm getting errors on the following lines:
    Me.EventArrived() += New EventArrivedEventHandler(watcher_EventArrived)
    (says I need to use RaiseEvent)
    Dim proc As New Win32_Process(TryCast(e.NewEvent("TargetInstance"), ManagementBaseObject))
    (says "too many arguments in sub new()")
    I can't find any other examples of a class like this for VB.NET so I'd be really grateful if you could help me get it working! :)

  • Worked Great!

    Thanks.

  • what is notepad.exe denote???
    and I guess we require SDK to run mgmtclassgen command

  • It is exactly what I need, get events when processes are started by user to monitor them. And much simplier than hook CreateProcess Win32 function.
    I can compile this class into a WPF application project, but I've no events raising never...
    Is there any issue to use this class on Windows 7 x64 system ?

  • Same problem here paslatek... can anyone point us to a good solution??

  • This code does not work for me. Can someone explain how to generate the Win32_Process class? The steps above does not work: I run the mgmtclassgen command from VS command Promt and it says "Code Generated Successfully!!!" But how do I get the Win32_Process class autogenerated in my project?

    Thanks

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

    procWatcher.Stop();
    }
    static void procWatcher_ProcessCreated(WMI.Win32.Win32_Process process)
    {
    Console.Write("\nCreated\n " + process.Name + " " + process.ProcessId +" "+ "DateTime:"+DateTime.Now);
    }

    static void procWatcher_ProcessDeleted(WMI.Win32.Win32_Process proc)
    {
    Console.Write("\nDeleted " + "DateTime:" + DateTime.Now);
    }

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

  • Hi there,

    I'm in the need of detecting when a certain process creates/modifies/deletes files in a predined folder.

    I need a notification saying that process "winword.exe" created a file in the folder "c:\files\".

    Now, is this possible using WMI or should I be looking in a different direction?

    Thanks in advance,
    Karl

  • Good article! I need a notification saying that process "winword.exe" created a file in the folder "c:\files\".

    Now, is this possible using WMI or should I be looking in a different direction?

    please help!
    thanks
    dhaval

Comments have been disabled for this content.