WMI __InstanceModificationEvent过滤

时间:2013-06-09 22:25:42

标签: c# .net events wmi monitoring

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

简而言之,我们希望创建一个通用系统,在该系统中可以订阅WMI数据实例中的多个更改。我们正在研究__InstanceModificationEvent来执行此操作:

以下原型代码监控任何记事本实例的所有更改:

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可以吗?实现我们想要的最佳实践是什么?

编辑:我知道可以编写一个查询,例如下面的查询,并循环轮询该值,但我们希望避免这种方法。

 SELECT PercentProcessorTime 
 FROM Win32_PerfFormattedData_PerfProc_Process 
 WHERE Name = "notepad"

1 个答案:

答案 0 :(得分:3)

__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 ";