【问题标题】:.NET Events for Process executable start进程可执行文件启动的 .NET 事件
【发布时间】:2010-10-25 07:39:20
【问题描述】:

有没有办法注册一个特定文件名的可执行文件启动时触发的事件?我知道通过获取进程句柄并注册退出的事件,在进程退出时获取事件很容易。但是,当一个尚未运行的进程启动时如何通知您...而不轮询所有正在运行的进程?

【问题讨论】:

    标签: c# .net events process


    【解决方案1】:

    您可以使用以下内容:

        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。

    【讨论】:

    • 这段代码可以重构,但我把它写得很冗长,希望能帮助理解
    • 其实这段代码看起来不错。但这对我不起作用。我错过了什么? win7,net 2.o项目。
    • 这对于紧凑的框架是否可行?我想为 windows mobile 6.5 做同样的事情。
    • 嘿,我返回的 ManagementBaseObject 对象的所有属性都设置为空,除了“句柄”。
    • @Hossein 您应该能够编辑 WatchForProcessStart 方法。删除 processName 参数,然后将 queryString 字符串更改为:"SELECT TargetInstance.Name FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process' ";
    【解决方案2】:

    WMI 可以在创建进程时创建事件。然后您可以过滤这些事件。

    【讨论】:

    • @Adam:我期待这个评论。不幸的是,自从我使用 WMI 事件(几年)而不是使用 .NET 以来已经有一段时间了,所以我必须自己学习如何去做......而且现在没有时间。
    【解决方案3】:

    这是代码。

    请注意,您必须像管理员一样启动 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);
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 2021-05-25
      • 2020-01-15
      • 1970-01-01
      相关资源
      最近更新 更多