System.Management.ManagementEventWatcher - 从断开连接中恢复

时间:2009-07-21 22:41:27

标签: c# .net wmi monitoring

我正在尝试构建一个可以通过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事件不会触发。尽管链接断开,但连接到ManagementEventWatcher的ManagementScope对象仍将IsConnected显示为true。

有没有人对如何检查连接状态有任何想法?

此时我唯一能想到的就是使用ManagementScope对象定期对机器执行WMI查询并确保仍然可以工作,尽管只能检查本地>远程连接而不是相应的remote->本地连接。我想我可以查找另一个可以用来验证连接的WMI查询(假设查询有效),但这似乎比我应该做的更多。

4 个答案:

答案 0 :(得分:2)

WMI中有两种事件使用者 - 临时和永久。您可能正在寻找的是永久性活动订阅。以下是关于MSDN的简要介绍

永久使用者是一个可以随时接收WMI事件的COM对象。永久事件使用者使用一组持久对象和过滤器来捕获WMI事件。与临时事件使用者一样,您可以设置一系列捕获WMI事件的WMI对象和过滤器。当发生与筛选器匹配的事件时,WMI会加载永久事件使用者并通知它有关该事件的信息。由于永久使用者是在WMI存储库中实现的并且是在WMI中注册的可执行文件,因此永久事件使用者在创建事件后操作和接收事件,甚至在WMI运行后重新启动操作系统之后也是如此。有关更多信息,请参阅始终接收事件。

这篇MSDN文章应该足以让你前进http://msdn.microsoft.com/en-us/library/aa393014(VS.85).aspx

但是,在处理此问题的情况下,我们选择轮询数据而不是创建永久消费者。另一种选择是监视某些事件(例如重新启动),然后重新注册临时事件使用者。

答案 1 :(得分:1)

查看此帖子here。它介绍了如何使用C#检测何时插入可移动磁盘。应该与您提供的WMI代码内联。

答案 2 :(得分:1)

订阅NetworkAvailabilityChange事件,这可以让您通过NetworkAvailabilityEventArgs.IsAvailable属性了解当前连接的状态。通过一些额外的工作,NetworkAddressChange事件将让您了解移动的机器,更改网络上的地址等。 。 。 System.Net.NetworkInformation有很好的信息。 。 。我假设你不介意使用WMI以外的东西来监控它。

答案 3 :(得分:0)

据我所知,当发生类似情况时,您应该收到类型ManagementException的异常,其中包含wbemErrCallCancelled WMI错误代码(0x80041032)。