Only one ManagementEventWatcher process listens for events at a time

I have written a C# program that reads WMI Instance operation events in a particular namespace. Another third-party software (SCCM client 1) is responsible for creating these instances in the background. When running multiple instances of my program, only the first one is able to listen to the events and fire the callback function. Rest of the processes keep looping without recording anything on the console. Furthermore, if I kill the first process and spawn a new one, none of the processes -- those already running or the new one -- are still able to read new Instance operation events, even though they are visible in the WMI Explorer tool. What stops other processes from also listening to these events?

class Program
{

    static ManagementEventWatcher watcher;


    static void StopListening(object sender, ConsoleCancelEventArgs e)
    {

        Console.WriteLine("Stopping listener");
        watcher.Stop();
        watcher.Dispose();

        watcher.EventArrived -= WmiEventArrived;
        
        Console.WriteLine("...stopped.");

    }

    static void Main(string[] args)
    {
        string ClassName = "CCM_StateMsg";
        string WmiQueryAsync = "SELECT * FROM __InstanceOperationEvent WHERE TargetInstance ISA '{0}'";
        string query = string.Format(CultureInfo.InvariantCulture, WmiQueryAsync, ClassName);

        string scope = @"root\ccm\StateMsg";

        watcher = new ManagementEventWatcher(scope, query);
        watcher.EventArrived += WmiEventArrived;

        Console.CancelKeyPress += StopListening;

        Console.WriteLine("Starting watcher");
        watcher.Start();
        Console.WriteLine("...started");

        while (true)
        {
            Console.WriteLine("Waiting for events...");
            Thread.Sleep(10000);
        }
    }

    public static void WmiEventArrived(object sender, EventArrivedEventArgs e)
    {

        // Choose type of event based on class name
        string eventClassName = (string)e.NewEvent.GetPropertyValue("__CLASS");

        Console.WriteLine("StateMessageProvider got event from WMI of type: {0}", eventClassName);

        ManagementBaseObject currInstance = (ManagementBaseObject)e.NewEvent.GetPropertyValue("TargetInstance");
        // RAISE THE EVENT            
        Console.WriteLine("GOT EVENT: {0}", e.NewEvent.ClassPath.ToString());

    }
}

Configuration Manager WMI namespaces and classes for Configuration Manager reports

Upvotes: 0

Views: 235

Answers (1)

erray
erray

Reputation: 121

The issue where your first program can only listen for WMI events and none of the subsequent instances can receive events may be related to the functionality of the ManagementEventWatcher class. This class has a structure that allows only one subscription at a time for a given query.

Can you this try?

 static void Main(string[] args) {
    string ClassName = "CCM_StateMsg";
    string WmiQueryAsync = "SELECT * FROM __InstanceOperationEvent WHERE TargetInstance ISA '{0}' AND SourceInstanceName='{1}'";
    
    // Generate a unique identifier for this instance
    string instanceId = Guid.NewGuid().ToString();

    string query = string.Format(WmiQueryAsync, ClassName, instanceId);
    string scope = @"root\ccm\StateMsg";

    watcher = new ManagementEventWatcher(scope, query);
    watcher.EventArrived += (sender, e) => WmiEventArrived(sender, e, instanceId);

}

public static void WmiEventArrived(object sender, EventArrivedEventArgs e, string instanceId)
{
    string eventInstanceId = (string)e.NewEvent.GetPropertyValue("SourceInstanceName");

    if (eventInstanceId != instanceId)
    {
        // Ignore events not intended for this instance
        return;
    }
}

Upvotes: 1

Related Questions