System.Management.ManagementEventWatcher - восстановление после отключения - PullRequest
3 голосов
/ 22 июля 2009

Я пытаюсь создать приложение, которое может контролировать несколько удаленных машин через WMI. Как разработчик C #, я решил использовать пространство имен System.Management.

Из соображений производительности и масштабируемости я бы предпочел использовать метод сбора информации, основанный на событиях, а не метод опроса. Поэтому я исследовал класс ManagementEventWatcher.

Для простых задач мониторинга этот класс кажется именно тем, что я хочу. Я создаю объект, назначаю ему параметры ManagementScope, EventQuery и EventWatcherOptions, подписываюсь на событие EventArrived и вызываю метод Start (упрощенный пример ниже).

  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;

Проблема, с которой я сталкиваюсь, заключается в том, что трудно обнаружить, когда соединение с удаленной машиной было разорвано различными способами (перезапуск машины, сбой маршрутизатора, отключение сетевого кабеля и т. Д.).

Класс ManagementEventWatcher, по-видимому, не предоставляет каких-либо средств определения того, что соединение было потеряно, поскольку событие Stopped не будет срабатывать при этом. Объект ManagementScope, прикрепленный к ManagementEventWatcher, по-прежнему показывает IsConnected как true, несмотря на неработающую ссылку.

У кого-нибудь есть идеи как проверить состояние соединения?

Единственное, что я могу сделать на этом этапе, - это использовать объект ManagementScope для периодического выполнения запроса WMI к машине и убедиться, что он по-прежнему работает, хотя он может проверять только локальное-> удаленное соединение, а не соответствующее удаленное-> локальное соединение. Я полагаю, что мог бы найти другой WMI-запрос, который мог бы использовать для проверки соединения (при условии, что запрос работает), но это похоже на большую работу, чем я должен был сделать.

Ответы [ 4 ]

2 голосов
/ 16 сентября 2009

В WMI есть два типа потребителей событий - временные и постоянные. То, что вы можете искать, это постоянная подписка на событие. Вот краткое сообщение об этом на MSDN

Постоянный потребитель - это COM-объект, который может постоянно получать событие WMI. Постоянный потребитель событий использует набор постоянных объектов и фильтров для захвата события WMI. Как временный потребитель событий, вы устанавливаете серию объектов WMI и фильтров, которые фиксируют событие WMI. Когда происходит событие, соответствующее фильтру, WMI загружает постоянного потребителя события и уведомляет его о событии. Поскольку постоянный потребитель реализован в репозитории WMI и является исполняемым файлом, который зарегистрирован в WMI, постоянный потребитель событий работает и получает события после его создания и даже после перезагрузки операционной системы, пока WMI работает. Для получения дополнительной информации см. Получение событий в любое время.

Этой статьи MSDN должно быть достаточно, чтобы вы начали http://msdn.microsoft.com/en-us/library/aa393014(VS.85).aspx.

Однако в моей ситуации при решении этой проблемы мы выбрали опрос данных, а не создание постоянного потребителя. Другой вариант - отслеживать определенные события (например, перезагрузку), а затем заново зарегистрировать временного потребителя событий.

1 голос
/ 12 января 2010

Подпишитесь на событие NetworkAvailabilityChange , это должно сообщить вам о состоянии вашего текущего соединения через свойство NetworkAvailabilityEventArgs.IsAvailable. С небольшой дополнительной работой событие NetworkAddressChange позволит вам узнать о машинах, которые перемещаются, меняют адреса и т. Д. В вашей сети. , , System.Net.NetworkInformation содержит полезную информацию. , , Я предполагаю, что вы не против использовать что-то кроме WMI для мониторинга этого.

1 голос
/ 02 сентября 2009

Проверьте этот пост здесь . В нем рассказывается, как определить, когда вставлен съемный диск с использованием C #. ДОЛЖЕН быть в соответствии с указанным вами кодом WMI.

0 голосов
/ 23 июля 2009

Насколько я могу судить, когда что-то подобное происходит, вы должны получить исключение типа ManagementException, содержащее код ошибки WMI wbemErrCallCancelled (0x80041032).

...