WMI __InstanceModificationEvent filtering

一世执手 提交于 2020-01-05 03:36:18

问题


We are designing a monitoring solution for our system, and we're looking into WMI as a possible option.

In short, we want to create a generic system where it shall be possible to subscribe to multiple changes in WMI data instances. We're looking into the __InstanceModificationEvent to do this:

The following prototype code monitors all changes on any instance of 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}"));
    }
}

So whenever any instance of notepad is changes, we will get an output like this (excerpt)

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

This is fine, however we need to improve this a bit. For example, let's pretend we are only interested in the changes to PercentProcessorTime. With the current code, the event will be fired whenever anything in the object changes. This is not good enough, because we might monitor hundreds of processes across multiple computers.

Thus, we need a way to specify that we only want the event to be triggered whenever this or that property changes, not the entire instance

Is this possible using WMI? What's the best practice to achieve what we want?

Edit: I know that it is possible to write a query such as the one below and cycically poll for the value, however we were hoping to avoid that approach.

 SELECT PercentProcessorTime 
 FROM Win32_PerfFormattedData_PerfProc_Process 
 WHERE Name = "notepad"

回答1:


The __InstanceModificationEvent has a reference to the previous instance so you might be able to compare values between the PreviousInstance and TargetInstance. For example, to filter for PercentProcessorTime changes:

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


来源:https://stackoverflow.com/questions/17014765/wmi-instancemodificationevent-filtering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!