作用域和静态函数的 C# 问题

C# problem with Scopes and static Functions

我正在编写一个程序,它将 expand/minimize 取决于另一个进程(游戏客户端)是否为 opened/terminated。 它将成为一个登录助手,在 windows 表单上显示帐户。

为了监控进程是否打开,我使用 C# 的 WMI。 这是我检查客户端状态的代码:

public static int Main(string[] args)
    {
        // query for filtering which process is montitored.
        string pol = "2";
        string queryString =
            "SELECT *" +
            "  FROM __InstanceOperationEvent " +
            "WITHIN  " + pol +
            " WHERE TargetInstance ISA 'Win32_Process' " +
            "   AND TargetInstance.Name = 'RiotClientCrashHandler.exe'"; // look for that process every 2 seconds.
        string scope = @"\.\root\CIMV2";

        ManagementEventWatcher startWatch = new ManagementEventWatcher(scope, queryString);
        startWatch.EventArrived += new EventArrivedEventHandler(startWatch_EventArrived); // event handler
        startWatch.Start();

        ManagementEventWatcher stopWatch = new ManagementEventWatcher(scope, queryString);
        stopWatch.EventArrived += new EventArrivedEventHandler(stopWatch_EventArrived); // event handler for terminating
        stopWatch.Start();

        Console.WriteLine("Press any key to exit");
        while (!Console.KeyAvailable) System.Threading.Thread.Sleep(50); // wait loop.

        startWatch.Stop();
        stopWatch.Stop();
        return 0;
    }

    
    static void stopWatch_EventArrived(object sender, EventArrivedEventArgs e)
    {
        Console.WriteLine("Process Stopped! Riot Client");
    }

    
    static void startWatch_EventArrived(object sender, EventArrivedEventArgs e)
    {
        Console.WriteLine("Process opened! Riot Client");
    }

非常基本的程序。事件的两个回调函数,即进程是started/terminated.

问题

客户端似乎没有一次调用这两个事件,而是每秒重新启动一次进程。 几秒钟后它重复调用:

我想用定时器实现一个定时器class:

        Timer timer = new Timer();
        timer.Elapsed += new ElapsedEventHandler(ClosingEvent);
        timer.Interval = 3000;
        timer.Start();

它应该等待一个设定的时间,在关闭事件被调用后(意味着进程必须完全终止)。 如果打开的事件被调用则重置。

我是从 C/Python/Javascript 开始接触 C# 的新手,所以不要对我有恶意。似乎我不能在这里声明一个全局变量,所以我有点困惑如何解决这个问题。我也不能从静态函数中调用非静态函数。 有办法解决吗?

  1. 我应该用计时器解决这个问题吗?
  2. 是否有使用 WMI 的不同方法?

一些事情。使用 __InstanceOperationEvent class 将为您提供命名空间的所有创建、删除和修改事件。这意味着任何时候流程实例上的任何 属性 发生变化,例如内存(经常发生),您都会收到一个要处理的事件。这就是为什么你会收到这么多事件。

我注意到的另一件事是您的 startWatch 和 stopWatch 代码共享同一个查询。这意味着您无论如何都会收到重复的事件,即使 WMI 事件只是在创建和删除时引发。您可以将它们组合到一个对象和事件处理程序中,然后处理您的代码中正在处理的事件类型,如下所示。

    public static int Main(string[] args)
    {
        // query for filtering which process is montitored.
        string pol = "2";
        string queryString =
            "SELECT *" +
            "  FROM __InstanceOperationEvent " +
            "WITHIN  " + pol +
            " WHERE TargetInstance ISA 'Win32_Process' " +
        "   AND TargetInstance.Name = 'RiotClientCrashHandler.exe'"; // look for that process every 2 seconds.
        string scope = @"\.\root\CIMV2";

        ManagementEventWatcher processWatcher = new ManagementEventWatcher(scope, queryString);
        processWatcher.EventArrived += new EventArrivedEventHandler(ProcessEventArrived); // event handler
        processWatcher.Start();

        Console.WriteLine("Press any key to exit");
        while (!Console.KeyAvailable) System.Threading.Thread.Sleep(50); // wait loop.

        processWatcher.Stop();
        return 0;
    }


    static void ProcessEventArrived(object sender, EventArrivedEventArgs e)
    {
        // Check the event arguments to see if the event being raised is creation or deletion
        switch (e.NewEvent.ClassPath.ClassName)
        {
            case "__InstanceCreationEvent":
                Console.WriteLine("Process opened! Riot Client");
                break;
            case "__InstanceDeletionEvent":
                Console.WriteLine("Process Stopped! Riot Client");
                break;
            default:
                break;
        }
    }

综上所述,如果可能,请尝试使用事件 class Win32_ProcessTrace 来提高性能。此 class 旨在仅处理进程启动和停止,因此它比查找 WMI 实例修改更精简。唯一的缺点是它需要更高的权限(管理员权限),这在您的环境中可能是不可能的。