【发布时间】:2010-10-25 07:39:20
【问题描述】:
有没有办法注册一个特定文件名的可执行文件启动时触发的事件?我知道通过获取进程句柄并注册退出的事件,在进程退出时获取事件很容易。但是,当一个尚未运行的进程启动时如何通知您...而不轮询所有正在运行的进程?
【问题讨论】:
有没有办法注册一个特定文件名的可执行文件启动时触发的事件?我知道通过获取进程句柄并注册退出的事件,在进程退出时获取事件很容易。但是,当一个尚未运行的进程启动时如何通知您...而不轮询所有正在运行的进程?
【问题讨论】:
您可以使用以下内容:
private ManagementEventWatcher WatchForProcessStart(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceCreationEvent " +
"WITHIN 10 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = @"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += ProcessStarted;
watcher.Start();
return watcher;
}
private ManagementEventWatcher WatchForProcessEnd(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceDeletionEvent " +
"WITHIN 10 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = @"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += ProcessEnded;
watcher.Start();
return watcher;
}
private void ProcessEnded(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject targetInstance = (ManagementBaseObject) e.NewEvent.Properties["TargetInstance"].Value;
string processName = targetInstance.Properties["Name"].Value.ToString();
Console.WriteLine(String.Format("{0} process ended", processName));
}
private void ProcessStarted(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject targetInstance = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value;
string processName = targetInstance.Properties["Name"].Value.ToString();
Console.WriteLine(String.Format("{0} process started", processName));
}
然后您可以调用 WatchForProcessStart 和/或 WatchForProcessEnd 并传入您的进程名称(例如“notepad.exe”)。
ManagementEventWatcher 对象是从两个 Watch* 方法返回的,因为它实现了 IDisposable,因此您应该在完成这些对象后调用 Dispose 以防止出现问题。
如果您需要在流程开始后更快地引发事件,您还可以更改查询中的轮询值。为此,将“WITHIN 10”行更改为小于 10。
【讨论】:
"SELECT TargetInstance.Name FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process' ";
WMI 可以在创建进程时创建事件。然后您可以过滤这些事件。
【讨论】:
这是代码。
请注意,您必须像管理员一样启动 Visual Studio 才能执行此代码。
using System;
using System.Management;
namespace AppLaunchDetector
{
class Program
{
static void Main(string[] args)
{
ManagementEventWatcher w = null;
WqlEventQuery q;
try
{
q = new WqlEventQuery();
q.EventClassName = "Win32_ProcessStartTrace";
w = new ManagementEventWatcher(q);
w.EventArrived += new EventArrivedEventHandler(ProcessStartEventArrived);
w.Start();
Console.ReadLine(); // block main thread for test purposes
}
catch (Exception ex)
{
}
finally
{
w.Stop();
}
}
static void ProcessStartEventArrived(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
Console.WriteLine("\n============================= =========");
Console.WriteLine("{0},{1},{2}", pd.Name, pd.Type, pd.Value);
}
}
}
}
【讨论】: