Search code examples
c#.netwmi

C#.NET Monitoring for a Process


We have this 3rd party in house app that's a little buggy and for now, till it's fixed, in our Citrix environment, I need to keep an eye on it and kill the process if it runs too long. I was able to poll for it and kill it if it was running but that's quite dirty and would require me to use a scheduled task. I want a service to monitor and detect it then kill it if it's running too long.

So I started a Windows Service project in Visual Studio and I found this code from CodeProject which registers with WMI using ManagementEventWatcher:

        string pol = "2";
        string appName = "MyApplicationName";

        string queryString =
            "SELECT *" +
            "  FROM __InstanceOperationEvent " +
            "WITHIN  " + pol +
            " WHERE TargetInstance ISA 'Win32_Process' " +
            "   AND TargetInstance.Name = '" + appName + "'";

        // You could replace the dot by a machine name to watch to that machine
        string scope = @"\\.\root\CIMV2";

        // create the watcher and start to listen
        ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
        watcher.EventArrived += new EventArrivedEventHandler(this.OnEventArrived);
        watcher.Start();

The problem with this code is that where it says "this.OnEventArrived", I get the following error:

Error 1 'MyServiceApp.Service1' does not contain a definition for 'OnEventArrived' and no extension method 'OnEventArrived' accepting a first argument of type 'MyServiceApp.Service1' could be found (are you missing a using directive or an assembly reference?)

What's the deal?


Solution

  • The documentation for this can be found on MSDN https://msdn.microsoft.com/en-us/library/system.management.managementeventwatcher.eventarrived%28v=vs.110%29.aspx

    OnEventArrived should look like this.

    private void OnEventArrived(object sender, ManagementEventArgs args)
    {
    //do your work here
    }
    

    Here is a sample program that will monitor notepad. You probably want to read more on WMI to see if there is a better way. You can launch notepad via the start menu and you will see Notepad started out put to the console. On exiting it will print Notepad Exited. I do not know all the messages that can be output.

        static void Main(string[] args)
        {
    
            string pol = "2";
            string appName = "Notepad.exe";
    
            string queryString =
                "SELECT *" +
                "  FROM __InstanceOperationEvent " +
                "WITHIN  " + pol +
                " WHERE TargetInstance ISA 'Win32_Process' " +
                "   AND TargetInstance.Name = '" + appName + "'";
    
            // You could replace the dot by a machine name to watch to that machine
            string scope = @"\\.\root\CIMV2";
    
            // create the watcher and start to listen
            ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
            watcher.EventArrived += new EventArrivedEventHandler(OnEventArrived);
            watcher.Start();
            Console.Read();
        }
    
        private static void OnEventArrived(object sender, EventArrivedEventArgs e)
        {
            if (e.NewEvent.ClassPath.ClassName.Contains("InstanceCreationEvent"))
                Console.WriteLine("Notepad started");
            else if (e.NewEvent.ClassPath.ClassName.Contains("InstanceDeletionEvent"))
                Console.WriteLine("Notepad Exited");
            else
                Console.WriteLine(e.NewEvent.ClassPath.ClassName);
        }