WMI __InstanceModificationEvent filtering

本文关键字:filtering InstanceModificationEvent WMI | 更新日期: 2023-09-27 18:17:44

我们正在为我们的系统设计一个监控解决方案,我们正在研究WMI作为一个可能的选择。

简而言之,我们想要创建一个通用系统,在这个系统中,可以订阅WMI数据实例中的多个更改。我们正在查看__InstanceModificationEvent来做这个:

下面的原型代码监视notepad的任何实例上的所有更改:

void StartMonitor()
{
    var query =   "SELECT * "
                + "FROM __InstanceModificationEvent "
                + "WITHIN 1 "
                + "WHERE TargetInstance Isa '"Win32_PerfFormattedData_PerfProc_Process'" "
                + "AND TargetInstance.Name = '"notepad'"";
    var scope = new ManagementScope(@"root'cimv2", null);
    scope.Connect();
    EventQuery qry = new EventQuery(query);
    ManagementEventWatcher w = new ManagementEventWatcher(scope, qry);
    w.EventArrived += EventArrived;
    w.Start();
}
void EventArrived(object sender, EventArrivedEventArgs e)
{
    var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach (var p in targetInstance.Properties)
    {
        Console.WriteLine(p.Name + ":'t" + (p.Value != null ? p.Value.ToString() : "{null}"));
    }
}

因此,当任何记事本的实例发生变化时,我们将得到如下输出(摘录)

  PageFileBytes:          1499136
  PageFileBytesPeak:      1740800
  PercentPrivilegedTime:  0
  PercentProcessorTime:   0
  PercentUserTime:        0
  PoolNonpagedBytes:      7040
  PoolPagedBytes:         172856

这很好,但是我们需要稍微改进一下。例如,假设我们只对PercentProcessorTime的更改感兴趣。在当前代码中,只要对象中的任何内容发生变化,就会触发该事件。这还不够好,因为我们可能会在多台计算机上监控数百个进程。

因此,我们需要一种方法来指定我们只希望在这个或那个属性发生变化时触发事件,而不是在整个实例 时触发事件。

是否可以使用WMI?实现我们想要的目标的最佳实践是什么?

Edit:我知道可以编写如下查询并循环轮询值,但是我们希望避免这种方法。

 SELECT PercentProcessorTime 
 FROM Win32_PerfFormattedData_PerfProc_Process 
 WHERE Name = "notepad"

WMI __InstanceModificationEvent filtering

__InstanceModificationEvent有对前一个实例的引用,因此您可能能够比较PreviousInstanceTargetInstance之间的值。例如,要过滤PercentProcessorTime更改:

var query =   "SELECT * "
            + "FROM __InstanceModificationEvent "
            + "WITHIN 1 "
            + "WHERE TargetInstance Isa '"Win32_PerfFormattedData_PerfProc_Process'" "
            + "AND TargetInstance.Name = '"notepad'" "
            + "AND PreviousInstance.PercentProcessorTime != TargetInstance.PercentProcessorTime ";