C# C-多个服务器的WMI查询太慢

C# C-多个服务器的WMI查询太慢,c#,multithreading,windows-server-2008,wmi,C#,Multithreading,Windows Server 2008,Wmi,我正在尝试从远程win2008服务器返回所有已启用的功能。只要我知道到底要问什么,那真的一点问题都没有 然而,我遇到的问题是,当我的查询没有找到结果时,验证该功能是否已安装需要花费很长时间——有时长达2分钟。查询超过600个节点时不够好 下面的代码是我发现的最快的方法,但是正如我所说的:返回false需要很长时间: public bool serverFeatureEnabled(string machineName, Win32_ServerFeature_ID id) {

我正在尝试从远程win2008服务器返回所有已启用的功能。只要我知道到底要问什么,那真的一点问题都没有

然而,我遇到的问题是,当我的查询没有找到结果时,验证该功能是否已安装需要花费很长时间——有时长达2分钟。查询超过600个节点时不够好

下面的代码是我发现的最快的方法,但是正如我所说的:返回false需要很长时间:

 public bool serverFeatureEnabled(string machineName, Win32_ServerFeature_ID id)
    {
        ManagementClass serviceClass = new ManagementClass("Win32_ServerFeature");
        string strScope = string.Format(@"\\{0}\root\cimv2", machineName);
        ConnectionOptions conOpt = new ConnectionOptions();
        serviceClass.Scope = new ManagementScope(strScope, conOpt);

        foreach (ManagementObject obj in serviceClass.GetInstances())
        {
            if ((UInt32)obj["ID"] == (uint)id)
            {
                return true;
            }

        }
        return false;
    }
是否有人有更好的想法来做这件事,我不介意它是否完全不使用WMI查询

我想做的就是把速度加快一点

我希望我有点道理

感谢您的帮助

编辑:

我曾尝试使用Sergrey V.提出的ManagementObjectSearcher类从服务器功能中直接选择所需的功能

它确实加快了第一个假消息的返回速度,但完成这一过程大约需要14秒,这将使集群中查询的所有服务器的upp时间增加到140分钟

编辑2:

我尝试使用WBEMTEST Windows Management Instrumentation Tester对Win32_ServerFeature运行测试,但与远程计算机的连接似乎是个问题-对其中一台远程计算机运行测试需要大约12秒才能连接,大约2秒才能返回数据


因此,Sergrey V提出的解决方案似乎是迄今为止WMI查询的最快解决方案。

尝试使用ManagementObjectSearcher类从服务器功能中直接选择所需功能:

            string serverName = "serverName";
            string className = "Win32_ServerFeature";
            string propertyName = "ID";
            int propertyValue = 144;
            string query = string.Format("SELECT * FROM {0} WHERE {1} = {2}", className, propertyName, propertyValue);
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            string scopePath = string.Format(@"\\{0}\root\cimv2", serverName);
            searcher.Scope = new ManagementScope(string.Format(scopePath));
            ManagementObjectCollection mCollection = searcher.Get();

            bool featureEnabled = mCollection.Count > 0;

尝试使用ManagementObjectSearcher类从服务器功能中直接选择所需功能:

            string serverName = "serverName";
            string className = "Win32_ServerFeature";
            string propertyName = "ID";
            int propertyValue = 144;
            string query = string.Format("SELECT * FROM {0} WHERE {1} = {2}", className, propertyName, propertyValue);
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            string scopePath = string.Format(@"\\{0}\root\cimv2", serverName);
            searcher.Scope = new ManagementScope(string.Format(scopePath));
            ManagementObjectCollection mCollection = searcher.Get();

            bool featureEnabled = mCollection.Count > 0;

不要连续运行操作。我不知道WMI内部是否存在瓶颈,但最明显的优化是并行运行整个过程。

不要串联运行操作。我不知道WMI在内部是否存在瓶颈,但最明显的优化是并行运行整个过程。

因此,我最后做的是: 首先,根据M Afifi的建议,我为列表中的每个节点启动了一个新任务。 然后使用“Task.Factory.StartNew”并行执行WMI查询。 使用System.Threading.Tasks

完全执行列表中的所有节点现在大约需要12秒

 referenceList.connectionNodes().ForEach(x =>
            {
                var genericTask = Task.Factory.StartNew(() =>
                    {
                        regkeyFactory.testParallelExecution(x);
                    });
            });

谢谢你们的帮助

我最后做的就是: 首先,根据M Afifi的建议,我为列表中的每个节点启动了一个新任务。 然后使用“Task.Factory.StartNew”并行执行WMI查询。 使用System.Threading.Tasks

完全执行列表中的所有节点现在大约需要12秒

 referenceList.connectionNodes().ForEach(x =>
            {
                var genericTask = Task.Factory.StartNew(() =>
                    {
                        regkeyFactory.testParallelExecution(x);
                    });
            });

谢谢你们的帮助

更快的方法是一体扫描,我使用ManagementClass创建了一个HWID类,只需0,07秒即可获得机器的唯一硬件id

更快的方法是一体扫描,我使用ManagementClass创建了一个HWID类,只需0,07秒即可获得机器的唯一硬件id

谢谢。这就大大加快了速度,从40秒左右返回false,到14秒左右。这确实是一个很好的改进,但每个服务器集群仍然需要140分钟。如果有人对如何在不使用WMI的情况下做到这一点有任何建议,我将非常高兴。执行该程序的帐户是域管理员帐户,任何端口都可以在远程机器上打开。谢谢。这就大大加快了速度,从40秒左右返回false,到14秒左右。这确实是一个很好的改进,但每个服务器集群仍然需要140分钟。如果有人对如何在不使用WMI的情况下做到这一点有任何建议,我将非常高兴。执行该程序的帐户是一个域管理员帐户,任何端口都可以在远程计算机上打开。@M Afifi谢谢,这也是我的想法-在包含所有主机名的列表上使用Parallel.ForEach方法System.System.Threading.Tasks。@Robinilsson您已经了解了它的要点:。现在有更丰富的并行库来完成任务,例如,取决于您的dotnet版本。@M Afifi-啊,看看这个!PLINQ将是有趣的,希望我能够同时连接到所有600个节点,所以我不需要等待140分钟,而应该在最慢的连接时间内完成这项工作。我会把结果发回来的@谢谢你的帮助!这正是我要找的。Task.Factory.StartNew的使用令人惊讶@抱歉,谢谢,这也是我的想法-在包含所有主机名的列表中使用Parallel.ForEach方法System.System.Threading.Tasks。@robininson您已经了解了要点:。现在有更丰富的并行库来完成任务,例如,取决于您的dotnet版本。@M Afifi-啊,看看这个!PLINQ将是有趣的,希望我能够同时连接到所有600个节点,因此我不必等待140分钟,而应该在最慢连接所需的时间内完成这项工作
待制作。我会把结果发回来的@谢谢你的帮助!这正是我要找的。Task.Factory.StartNew的使用令人惊讶!