使用WMI处理启动事件 - 未检测到所有进程启动

时间:2012-04-13 10:37:06

标签: c# events process wmi wql

我在Windows服务(运行为NT_AUTHORITY\SYSTEM)中使用以下C#代码来创建用于接收进程创建事件的事件处理程序(使用WMI和WQL):

string queryString = "SELECT * FROM Win32_ProcessStartTrace";
ManagementEventWatcher watcher = new ManagementEventWatcher(new WqlEventQuery(queryString));
watcher.EventArrived += new EventArrivedEventHandler(ProcessStartEvent);
watcher.Start();

ProcessStartEvent

int processId = int.Parse(e.NewEvent.Properties["ProcessId"].Value.ToString());
Process proc = Process.GetProcessById(processId);

Out("Received process: " + proc.ProcessName);

我遇到的问题是(由于一些奇怪的原因)并非所有进程启动都被捕获并由程序报告。如果我同时开始大约6个进程,则可能不会在输出中显示。

我尝试使用WMI对捕获进程创建事件进行一些研究,但是可用的信息有限。我已经看到也可以使用类似的东西捕获进程开始:

SELECT TargetInstance
FROM __InstanceCreationEvent
WITHIN  2
WHERE TargetInstance ISA 'Win32_Process'

(见this Stack Overflow answer

使用__InstanceCreationEventWin32_ProcessStartTrace之间是否存在重大差异?这可能是我遇到问题的原因吗?

是否有解释为什么我没有收到 所有 进程启动的事件?是否有更明显的事情我在这里做错了?

2 个答案:

答案 0 :(得分:7)

这两种方法都有效但以不同的方式工作。

当您使用__InstanceCreationEvent WMI类时,您正在使用intrinsic事件,这意味着您正在监视标准WMI数据模型中的更改(这类似于表中的触发器)。

当您使用Win32_ProcessStartTrace时,您正在使用Extrinsic事件,这意味着您正在使用为特定任务制作的专门事件类,在此情况下监视进程创建。

现在回到您的问题,避免某些事件“丢失”的最佳方法是创建permanent event consumer

答案 1 :(得分:4)

我发现当你得到一个进程已经开始的事件时 - 将该事件传递给一个单独的线程,例如使用boost线程,你可以将进程ID传递给一个新线程。

这意味着WMI COM不会陷入困境并停止工作。

请参阅http://sourceforge.net/p/processhistory/code/HEAD/tree/trunk/PHLogger/COM_WMI_Consumer/

用于某些可用的C ++代码。