监听远程 Windows 服务器订阅上的 wmi 进程关闭事件似乎“滞后”;并需要一段时间才能真正订阅

发布于 2025-01-15 06:21:38 字数 3835 浏览 0 评论 0原文

我在 .Net Framework 4.7.2 应用程序中使用 Microsoft.Management.Infrastruct (1.0.0) 包。

我使用 CIM* 类在远程计算机上启动一个进程并监听它何时完成。

我将 powershell 作为标签,因为这可以(并且可能更常见)使用 powershell 完成,所以我不想错过这些专业知识和智慧。

对于我正在执行此操作的五分之四的服务器,我没有任何问题并且效果很好。但对于其中一个来说,监听进程退出事件的订阅似乎在很长一段时间内都没有开始触发(我说的是几分钟),此时我开始并想知道的进程已经完成,已经完成完成后,我等待一个永远不会发生的进程退出事件。

无论如何,这是一个小型控制台应用程序,它应该允许您做我正在做的事情。它非常简单。我不知道我是否做错了什么(如果是这样,为什么它对其他人起作用),或者服务器配置是否可能导致问题,或者它是否只是“有时就是这样”的情况。

---- 代码 -----

所需的 Nuget 包 Microsoft.Management.Infrastruct 1.0.0

using System;
using System.Linq;
using System.Management;
using Microsoft.Management.Infrastructure;

namespace CimEventListener
{
    class Program
    {
        static void Main(string[] args)
        {
            const string cimNmspc = @"root\cimv2";
            Console.WriteLine("Enter Server Name to listen to");
            var serverName = Console.ReadLine();
            using (var session = CimSession.Create(serverName))
            using (var observer = new CimObserver())
            {
                if (!TestConnection(session))
                {
                    Console.Error.WriteLine($"Failed to create CimSession with machine: {serverName}");
                    Environment.Exit( -1);
                }

                observer.EventArrived += (s, res) =>
                {
                    var exitingProcessId = (uint)res.Instance.CimInstanceProperties["ProcessId"].Value;
                    var exitingProcessName = $"{res.Instance.CimInstanceProperties["ProcessName"].Value}";

                    Console.WriteLine($"Process Exited - ID: {exitingProcessId}  Name: {exitingProcessName}");
                };

                var wqlQuery = new WqlEventQuery("Win32_ProcessStopTrace"); //use this as it encapsulates the building of the query string
                using (var processParams = new CimMethodParametersCollection())
                using (session.SubscribeAsync(cimNmspc, wqlQuery.QueryLanguage, wqlQuery.QueryString).Subscribe(observer))
                {
                    Console.WriteLine("Press Enter to stop listening");
                    Console.ReadLine();
                }
            }
            Console.WriteLine("Complete");
            
        }

        // not strictly required but left it in as its useful for anyone running this
        private static bool TestConnection(CimSession session)
        {
            if (!session.TestConnection(out var identityResp, out var cimException))
            {
                Console.Error.WriteLine($"Could not connect. Exception: {cimException}");
                return false;
            }
            else
            {
                using (identityResp)
                {
                    var details = string.Join(" | ", identityResp.CimInstanceProperties.Select(p => (p.Name, p.Value)));
                    Console.WriteLine($"Successfully Create CIM Session. Details: {details}");
                    return true;
                }
            }
        }
    }

   // just a helper class
    class CimObserver : IObserver<CimSubscriptionResult>, IDisposable
    {
        public event EventHandler<CimSubscriptionResult> EventArrived;

        public event EventHandler Completed;


        public void OnCompleted()
        {
            Completed?.Invoke(this, EventArgs.Empty);
        }
        public void OnError(Exception error) => throw error;

        public void OnNext(CimSubscriptionResult value) => EventArrived?.Invoke(this, value);

        public void Dispose()
        {
            EventArrived = null;
            Completed = null;
        }
    }
}

我对服务器 x 运行这个小控制台应用程序,如果我登录到服务器 x,几乎立即会看到正在退出的各种后台进程并启动并杀死记事本我看到它

但是服务器 y - 一开始我什么也没看到,即使登录并启动和停止进程,仍然什么也没有,然后几分钟后,它开始给我事件。

有什么想法可能导致这种情况吗?

I'm using the Microsoft.Management.Infrastructure (1.0.0) package in a .Net Framework 4.7.2 application.

I'm using the CIM* classes to start a process on a remote machine and listen for when it finishes.

I've included powershell as a tag as this could be (and probably a lot more often is) done with powershell, so I didn't want to miss out on those expertise and wisdom.

For 4 out of 5 of the servers I'm doing this on, I have no issue and it works great. But for one of them the subscription to listen to the process exiting event, seems to not start firing for a good chunk of time (I'm talking minutes) and by this point the process I started and wanted to know had finished, had already finished and I'm left waiting for a process exit event that will never happen.

Anyway here is a small console app, that should allow you to do what I'm doing. Its pretty simple. I don't know if I'm doing something wrong (if so why does it work on the others) or if potentially the server configuration is causing issues or if its just a ' thats just how it is sometimes' scenario.

---- The Code -----

Required Nuget Package Microsoft.Management.Infrastructure 1.0.0

using System;
using System.Linq;
using System.Management;
using Microsoft.Management.Infrastructure;

namespace CimEventListener
{
    class Program
    {
        static void Main(string[] args)
        {
            const string cimNmspc = @"root\cimv2";
            Console.WriteLine("Enter Server Name to listen to");
            var serverName = Console.ReadLine();
            using (var session = CimSession.Create(serverName))
            using (var observer = new CimObserver())
            {
                if (!TestConnection(session))
                {
                    Console.Error.WriteLine(
quot;Failed to create CimSession with machine: {serverName}");
                    Environment.Exit( -1);
                }

                observer.EventArrived += (s, res) =>
                {
                    var exitingProcessId = (uint)res.Instance.CimInstanceProperties["ProcessId"].Value;
                    var exitingProcessName = 
quot;{res.Instance.CimInstanceProperties["ProcessName"].Value}";

                    Console.WriteLine(
quot;Process Exited - ID: {exitingProcessId}  Name: {exitingProcessName}");
                };

                var wqlQuery = new WqlEventQuery("Win32_ProcessStopTrace"); //use this as it encapsulates the building of the query string
                using (var processParams = new CimMethodParametersCollection())
                using (session.SubscribeAsync(cimNmspc, wqlQuery.QueryLanguage, wqlQuery.QueryString).Subscribe(observer))
                {
                    Console.WriteLine("Press Enter to stop listening");
                    Console.ReadLine();
                }
            }
            Console.WriteLine("Complete");
            
        }

        // not strictly required but left it in as its useful for anyone running this
        private static bool TestConnection(CimSession session)
        {
            if (!session.TestConnection(out var identityResp, out var cimException))
            {
                Console.Error.WriteLine(
quot;Could not connect. Exception: {cimException}");
                return false;
            }
            else
            {
                using (identityResp)
                {
                    var details = string.Join(" | ", identityResp.CimInstanceProperties.Select(p => (p.Name, p.Value)));
                    Console.WriteLine(
quot;Successfully Create CIM Session. Details: {details}");
                    return true;
                }
            }
        }
    }

   // just a helper class
    class CimObserver : IObserver<CimSubscriptionResult>, IDisposable
    {
        public event EventHandler<CimSubscriptionResult> EventArrived;

        public event EventHandler Completed;


        public void OnCompleted()
        {
            Completed?.Invoke(this, EventArgs.Empty);
        }
        public void OnError(Exception error) => throw error;

        public void OnNext(CimSubscriptionResult value) => EventArrived?.Invoke(this, value);

        public void Dispose()
        {
            EventArrived = null;
            Completed = null;
        }
    }
}

I run this little console app against server x and almost immediately a see various background processes that are exiting coming through if I login to server x and start and kill note pad I see it

However server y - I see nothing at first and even if log on and start and stop a process, still nothing and then several minutes later, it starts giving me events.

Any ideas what could be causing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文