views:

920

answers:

4

I am attempting to build an application that can monitor multiple remote machines through WMI. As a C# developer, I have chosen to utilize the System.Management namespace.

For performance and scalability reasons, I would much prefer to use an event-driven method of gathering information than a poll-based one. As such, I have been investigating the ManagementEventWatcher class.

For simple monitoring tasks, this class seems to be exactly what I want. I create the object, give it ManagementScope, EventQuery, and EventWatcherOptions parameters, subscribe to the EventArrived event, and call the Start method (simplified example below).

  using SM = System.Management;

  ...

  SM.ManagementEventWatcher    _watcher;
  SM.ConnectionOptions         conxOptions;
  SM.ManagementScope           scope;
  SM.WqlEventQuery             eventQuery;
  SM.EventWatcherOptions       eventOptions;
  SM.EventArrivedEventHandler  handler;

  string  path = @"\\machine\root\cimv2";

  conxOptions = new SM.ConnectionOptions ();
  conxOptions.Username = user;
  conxOptions.Password = password;
  scope = new SM.ManagementScope (path, conxOptions);
  scope.Connect ();

  eventQuery = new SM.WqlEventQuery ("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'");

  eventOptions = new SM.EventWatcherOptions ();
  eventOptions.Context.Add ("QueryName", "Process Query");

  _watcher = new SM.ManagementEventWatcher (scope, eventQuery, eventOptions);
  handler = new SM.EventArrivedEventHandler (HandleWMIEvent);
  _watcher.EventArrived += handler;
  _watcher.Start ();

  Console.WriteLine ("Press Any Key To Continue");
  Console.ReadKey ();

  _watcher.Stop ();
  _watcher.EventArrived -= handler;

The problem I am running into is that it is difficult to detect when the connection to the remote machine has been broken through various means (machine restart, downed router, unplugged network cable, etc.).

The ManagementEventWatcher class does not appear to provide any means of determining that the connection has been lost, as the Stopped event will not fire when this occurs. The ManagementScope object attached to the ManagementEventWatcher still shows IsConnected as true, despite the broken link.

Does anyone have any ideas on how to check the connection status?

The only thing I can think to do at this point is to use the ManagementScope object to periodically perform a WMI query against the machine and make sure that still works, though that can only check the local->remote connection and not the corresponding remote->local connection. I suppose I could look up another WMI query I could use to verify the connection (assuming the query works), but that seems like more work than I should have to do.

A: 

As far as I can tell, when something like that happens you should receive an exception of type ManagementException that contains wbemErrCallCancelled WMI error code (0x80041032).

Uros Calakovic
I have found that the ManagementEventWatcher.Stopped event is fired if the WMI service on the remote machine is restarted, but any other scenario (e.g. reboot, network disconnection, etc.), and I get nothing.In the meantime, I looked into subscribing to an event to provide a form of heartbeat I can rely upon.For any WindowsXP machine and later, I can use "SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA 'Win32_UTCTime' AND (TargetInstance.Seconds=0 OR TargetInstance.Seconds=30)" to provide a 30-second heartbeat.That may ultimately have to be my answer, I'm afraid.
A: 

Check out this post here. It covers how to detect when a removable disk is inserted using C#. SHould be inline with your WMI code that you supplied.

SwDevMan81
A: 

There are two kinds of event consumers in WMI - temporary and permanent. What you might be looking for is a permanent event subscription. Here is a brief blurb about that on MSDN

A permanent consumer is a COM object that can receive a WMI event at all times. A permanent event consumer uses a set of persistent objects and filters to capture a WMI event. Like a temporary event consumer, you set up a series of WMI objects and filters that capture a WMI event. When an event occurs that matches a filter, WMI loads the permanent event consumer and notifies it about the event. Because a permanent consumer is implemented in the WMI repository and is an executable file that is registered in WMI, the permanent event consumer operates and receives events after it is created and even after a reboot of the operating system as long as WMI is running. For more information, see Receiving Events at All Times.

This MSDN article should be enough to get you going http://msdn.microsoft.com/en-us/library/aa393014%28VS.85%29.aspx.

However, in my situation in dealing with this problem, we chose to poll for the data as opposed to creating a permanent consumer. Another option is to monitor for certain events (such as a reboot) and then re-register your temporary event consumer.

Mark
A: 

Subscribe to the NetworkAvailabilityChange event, this should let you know about the status of your current connection through the NetworkAvailabilityEventArgs.IsAvailable property. With a little extra work the NetworkAddressChange event will let you know about machines that move about, change addresses and etc on your network . . . The System.Net.NetworkInformation has good information . . . I' assuming you don't mind using something other than WMI to monitor this.

TheEruditeTroglodyte