我需要在某些过程被启动或停止在Windows计算机上观看。我目前挖掘到的WMI系统和查询它每隔5秒,但是这会导致CPU峰值每5秒钟,因为WMI是WMI。是否有这样做的更好的办法?我可以只让正在运行的进程的列表,并通过System.Diagnostics命名空间附加一个Exited事件给他们,但没有事件处理程序的创建。

有帮助吗?

解决方案

这不正是你如何做到这一点在现实世界中,但应该有所帮助。这似乎不开车我的CPU多的。

    static void Main(string[] args)
    {
        // Getting all instances of notepad
        // (this is only done once here so start up some notepad instances first)
        // you may want use GetProcessByPid or GetProcesses and filter them as required
        Process[] processesToWatch = Process.GetProcessesByName("notepad");

        foreach (var process in processesToWatch)
        {
            process.EnableRaisingEvents = true;
            process.Exited +=
                (s, e) => Console.WriteLine("An instance of notepad exited");
        }

        Thread watchThread = new Thread(() =>
            {
                while (true)
                {
                    Process[] processes = Process.GetProcesses();
                    foreach (var process in processes)
                    {
                        Console.WriteLine("{0}:{1}", process.Id, process.ProcessName);
                    }
                    // Don't dedicate a thread to this like I'm doing here
                    // setup a timer or something similiar
                    Thread.Sleep(2000);
                }
            });
        watchThread.IsBackground = true;
        watchThread.Start();

        Console.WriteLine("Polling processes and waiting for notepad process exit events");
        Console.ReadLine();
    }

其他提示

听哪里我都无法从我的退出/清除事件正确地分离的情况下WMI事件时,我不得不CPU峰值。你可能想看看你是不是“泄漏” WMI事件订阅。以防万一,尽可能早地从事件分离,并确保你总是这样做。

要进一步说明,这里是从我PowerShell的书,听为例使用PSEventing库WMI事件:

  

...添加-PSSnapin PSEventing -ErrorAction   SilentlyContinue

     

$的queryString = @”       选择 *       从__InstanceModificationEvent       在10       哪里           TargetInstance ISA 'win32_service时'           和TargetInstance.Name = 'W3SVC'           AND TargetInstance.State = '停止'“@

     

$查询=新物体System.Management.WQLEventQuery`       -ArgumentList $的queryString

     

$观察者=新物体   System.Management.ManagementEventWatcher($查询)

     

连接-EventListener的观察者   EventArrived

     

$ watcher.Start()

     

回声“等待W3CSVC服务   停止...”获取,事件-wait | foreach {           写主机-foreground红“W3SVC服务已停止!”       }

     

$ watcher.Stop()

     

断开-EventListener的观察者EventArrived

     

回声 “完成”

如果我不这样做的断开,事件监听在脚本退出位,我得到的CPU峰值第三次或第四次我重视的事件。我的猜测是,该系统还尝试传递的事件。

如果你只是在寻找你的进程PID /名称,你可能会想挑上Win32_ProcessTrace事件,使用WQL查询,如“SELECT * FROM Win32_ProcessTrace WHERE TargetInstance.ProcessName =‘名’” 如果适用*

使用 “SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32Process' AND TargetInstance.Name = '名称'” 是在它的工作原理在后端的陷阱。如果你检查你的wbemess.log%WINDIR%以内\ SYSTEM32 \ WBEM \ logs目录,你会发现下面的日志(使用__InstanceDeletionEvent):

(Wed Jul 22 13:58:31 2009.73889577) : Registering notification sink with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 047209E0 with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 0225E560 with query select * from __ClassOperationEvent where TargetClass isa "Win32_Process" in namespace //./root/CIMV2.
(Wed Jul 22 13:58:31 2009.73889577) : Activating filter 'select * from __ClassOperationEvent where TargetClass isa "Win32_Process"' with provider $Core
(Wed Jul 22 13:58:31 2009.73889587) : Activating filter 'select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process'' with provider $Core
(Wed Jul 22 13:58:31 2009.73889587) : Instituting polling query select * from Win32_Process to satisfy event query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process'
(Wed Jul 22 13:58:31 2009.73889587) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2'
(Wed Jul 22 13:58:31 2009.73889697) : Polling query 'select * from Win32_Process' done
(Wed Jul 22 13:58:41 2009.73899702) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2'
(Wed Jul 22 13:58:41 2009.73899792) : Polling query 'select * from Win32_Process' done

可以看到,远程机器上的实际事件的实现是在由您在WITHIN子句值所指定的时间间隔执行针对Win32_Process的查询。其结果是,开始和任何流程,轮询内停止将永远不会触发一个事件。

您可以设置WITHIN子句较小值,以尽量减少这种影响,但更好的方法是使用像Win32_ProcessTrace一个真正的事件,应总是火。

*注意的MSDN表明Win32_ProcessTrace需要一个服务器上最小的Windows XP客户机上和Windows 2003的工作。如果您正在使用旧的操作系统时,您可以使用__InstanceModificationEvent查询被卡住。

我的回答这里提到比WMI其他的替代: https://stackoverflow.com/a/50315772/3721646 如果设计不当,WMI查询可以花费大量CPU的性能。如果从Win32_Process类的内部事件被用于跟踪过程创建事件,这会影响性能严重。另一种方法是利用安全审计日志。您可以使用本地安全策略或在多台机器的情况下使用GPO启用过程跟踪。一旦这个过程跟踪开始,您可以订阅安全事件日志使用自定义XML查询来监控您感兴趣的某些进程。进程创建事件ID是4688.`

<QueryList>
 <Query Id="0" Path="Security">
   <Select Path="Security">
       *[EventData[Data[@Name='NewProcessName'] ='C:\Windows\explorer.exe']]
       and
       *[System[(EventID=4688)]]
   </Select>
 </Query>
</QueryList>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top