我需要观察在Windows计算机上启动或停止某些进程的时间。我目前正在进入WMI系统并每隔5秒查询一次,但由于WMI是WMI,因此每隔5秒就会出现一次CPU峰值。有没有更好的方法呢?我可以只列出正在运行的进程并通过System.Diagnostics命名空间将Exited事件附加到它们,但是没有用于创建的事件处理程序。
答案 0 :(得分:1)
这不完全是你在现实世界中的表现,但应该有所帮助。这似乎根本不会驱动我的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();
}
答案 1 :(得分:1)
在我退出/清理时无法正确分离事件的情况下,我在收听WMI事件时遇到CPU峰值。您可能想要检查您是否“泄漏”WMI事件订阅。以防万一从事件中脱离,并确保你总是这样做。
为了进一步说明,这里是my PowerShell book使用PSEventing库监听WMI事件的示例:
Add-PSSnapin PSEventing -ErrorAction SilentlyContinue
$ queryString = @' 选择 * FROM __InstanceModificationEvent 在10 哪里 TargetInstance ISA'Win32_Service' AND TargetInstance.Name ='w3svc' AND TargetInstance.State ='已停止''@
$ query = New-Object System.Management.WQLEventQuery` -argumentList $ queryString
$ watcher = New-Object System.Management.ManagementEventWatcher($查询)
Connect-EventListener观察者 EventArrived
$ watcher.Start()
echo“等待W3CSVC服务 停止......“Get-Event -wait |
foreach {
Write-Host -foreground Red“W3SVC服务已停止!” }$ watcher.Stop()
Disconnect-EventListener观察者EventArrived
回声“完成”
如果我在脚本退出时没有执行 Disconnect-EventListener 位,我会在第三次或第四次附加到事件时获得CPU峰值。我的猜测是系统仍然试图传递事件。
答案 2 :(得分:1)
如果您只是在寻找进程的PID /名称,您可能希望使用WQL查询来获取Win32_ProcessTrace事件,例如“SELECT * FROM Win32_ProcessTrace WHERE TargetInstance.ProcessName ='name'”如果适用* 。
使用“SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance ISA'Win32Process'AND TargetInstance.Name ='name'”的缺陷在于它在后端的工作原理。如果检查%windir%\ system32 \ wbem \ logs目录中的wbemess.log,您会注意到以下日志(使用__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查询的问题。
答案 3 :(得分:0)
我在这里的回答提到了除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>