我正在尝试构建一个可以通过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查询,并确保它仍然有效,尽管那只能检查本地->远程连接,而不是相应的远程. ->本地连接.我想我可以查找另一个可以用来验证连接的WMI查询(假设查询有效),但这似乎比我应该做的工作还要多.
解决方法:
WMI中有两种事件使用者-临时和永久.您可能正在寻找的是永久性事件订阅.这是有关MSDN的简要介绍
永久使用者是可以始终接收WMI事件的COM对象.永久事件使用者使用一组持久对象和筛选器来捕获WMI事件.像临时事件使用者一样,您可以设置一系列WMI对象和捕获WMI事件的过滤器.当发生与过滤器匹配的事件时,WMI会加载永久事件使用者并通知该事件.由于永久使用者在WMI存储库中实现,并且是在WMI中注册的可执行文件,因此只要创建了永久使用者,就可以在其创建后甚至在重新启动操作系统之后运行并接收事件,只要WMI正在运行即可.有关更多信息,请参阅始终接收事件.
这篇MSDN文章应该足以使您继续前进http://msdn.microsoft.com/en-us/library/aa393014(VS.85).aspx.
但是,在处理此问题的情况下,我们选择轮询数据,而不是创建一个永久使用者.另一个选择是监视某些事件(例如重新启动),然后重新注册您的临时事件使用者.