8

我在 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中所见)

__InstanceCreationEvent使用和之间有什么主要区别Win32_ProcessStartTrace吗?这可能是我的问题的原因吗?

有没有解释为什么我没有收到所有流程开始的事件?我在这里做错了什么更明显的事情吗?

4

2 回答 2

8

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

当您使用__InstanceCreationEventWMI 类时,您使用的是内部事件,这意味着您正在监视标准 WMI 数据模型中的更改(这就像表中的触发器一样工作)。

当您使用时,Win32_ProcessStartTrace您正在使用外部事件,这意味着您正在使用为特定任务制作的专用事件类,在这种情况下监控流程创建。

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

于 2012-04-13T15:50:30.267 回答
4

我发现当您收到一个进程已启动的事件时 - 将该事件传递给一个单独的线程,例如 boost 线程,您可以将进程 ID 传递给一个新线程。

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

请参阅http://sourceforge.net/p/processhistory/code/HEAD/tree/trunk/PHLogger/并使用 COM_WMI_Consumer/ 查找修订版

对于一些工作 C++ 代码。

于 2013-05-01T20:20:48.077 回答