1

I'm using the Microsoft.Management.Infrastructure (1.0.0) package in a .Net Framework 4.7.2 application.

I'm using the CIM* classes to start a process on a remote machine and listen for when it finishes.

I've included powershell as a tag as this could be (and probably a lot more often is) done with powershell, so I didn't want to miss out on those expertise and wisdom.

For 4 out of 5 of the servers I'm doing this on, I have no issue and it works great. But for one of them the subscription to listen to the process exiting event, seems to not start firing for a good chunk of time (I'm talking minutes) and by this point the process I started and wanted to know had finished, had already finished and I'm left waiting for a process exit event that will never happen.

Anyway here is a small console app, that should allow you to do what I'm doing. Its pretty simple. I don't know if I'm doing something wrong (if so why does it work on the others) or if potentially the server configuration is causing issues or if its just a ' thats just how it is sometimes' scenario.

---- The Code -----

Required Nuget Package Microsoft.Management.Infrastructure 1.0.0

using System;
using System.Linq;
using System.Management;
using Microsoft.Management.Infrastructure;

namespace CimEventListener
{
    class Program
    {
        static void Main(string[] args)
        {
            const string cimNmspc = @"root\cimv2";
            Console.WriteLine("Enter Server Name to listen to");
            var serverName = Console.ReadLine();
            using (var session = CimSession.Create(serverName))
            using (var observer = new CimObserver())
            {
                if (!TestConnection(session))
                {
                    Console.Error.WriteLine($"Failed to create CimSession with machine: {serverName}");
                    Environment.Exit( -1);
                }

                observer.EventArrived += (s, res) =>
                {
                    var exitingProcessId = (uint)res.Instance.CimInstanceProperties["ProcessId"].Value;
                    var exitingProcessName = $"{res.Instance.CimInstanceProperties["ProcessName"].Value}";

                    Console.WriteLine($"Process Exited - ID: {exitingProcessId}  Name: {exitingProcessName}");
                };

                var wqlQuery = new WqlEventQuery("Win32_ProcessStopTrace"); //use this as it encapsulates the building of the query string
                using (var processParams = new CimMethodParametersCollection())
                using (session.SubscribeAsync(cimNmspc, wqlQuery.QueryLanguage, wqlQuery.QueryString).Subscribe(observer))
                {
                    Console.WriteLine("Press Enter to stop listening");
                    Console.ReadLine();
                }
            }
            Console.WriteLine("Complete");
            
        }

        // not strictly required but left it in as its useful for anyone running this
        private static bool TestConnection(CimSession session)
        {
            if (!session.TestConnection(out var identityResp, out var cimException))
            {
                Console.Error.WriteLine($"Could not connect. Exception: {cimException}");
                return false;
            }
            else
            {
                using (identityResp)
                {
                    var details = string.Join(" | ", identityResp.CimInstanceProperties.Select(p => (p.Name, p.Value)));
                    Console.WriteLine($"Successfully Create CIM Session. Details: {details}");
                    return true;
                }
            }
        }
    }

   // just a helper class
    class CimObserver : IObserver<CimSubscriptionResult>, IDisposable
    {
        public event EventHandler<CimSubscriptionResult> EventArrived;

        public event EventHandler Completed;


        public void OnCompleted()
        {
            Completed?.Invoke(this, EventArgs.Empty);
        }
        public void OnError(Exception error) => throw error;

        public void OnNext(CimSubscriptionResult value) => EventArrived?.Invoke(this, value);

        public void Dispose()
        {
            EventArrived = null;
            Completed = null;
        }
    }
}

I run this little console app against server x and almost immediately a see various background processes that are exiting coming through if I login to server x and start and kill note pad I see it

However server y - I see nothing at first and even if log on and start and stop a process, still nothing and then several minutes later, it starts giving me events.

Any ideas what could be causing this?

Dave
  • 2,829
  • 3
  • 17
  • 44

0 Answers0