繁体   English   中英

当 RPC 服务器不可用时设置远程 WMI 超时

[英]Set Timeout On Remote WMI when RPC Server Is Unavailable

我有以下代码可以检查远程计算机上服务的状态。 问题是,如果找不到远程计算机(它已关闭或其他原因),则ManagementObjectSearcher.Get()方法需要 20 秒才能抛出“RPC 服务器不可用”的错误。 在服务器不可用的情况下,我想明确声明我只希望它尝试一小段时间(如 3 秒)。 我已经关注了此处的帖子,但它声明在 ManagementObjectSearcher 上使用超时选项,但我的代码似乎忽略了该值(因为它声明它与集合无关)。 这些选项有什么我忽略的吗? 我也尝试过使用ReturnImmediatly属性,但无济于事。

public static void WmiServiceCheck()
    {
        try
        {
            var computerName = "SomeInvalidComputer";
            var serviceName = "Power";
            var managementScope = new ManagementScope(string.Format(@"\\{0}\root\cimv2", computerName));
            var objectQuery = new ObjectQuery(string.Format("SELECT * FROM Win32_Service WHERE Name = '{0}'", serviceName));
            var searcher = new ManagementObjectSearcher(managementScope, objectQuery);
            searcher.Options.Timeout = new TimeSpan(0, 0, 0, 3); // Timeout of 3 seconds
            var managementObjectCollection = searcher.Get();
            var serviceState = managementObjectCollection.Cast<ManagementObject>().ToList().Single()["State"].ToString();
            /// Other stuff here
        }
        catch (Exception ex)
        {
        }
    }

是的,不是那个。 您要设置 ConnectionOptions.Timeout:

  var managementScope = new ManagementScope(...);
  managementScope.Options.Timeout = TimeSpan.FromSeconds(3);

当我测试它时效果很好。

请记住,3 秒处于低端,如果有一段时间没有查询,服务器很可能不得不将大量代码交换到 RAM 中来处理请求。 如果服务器以其他方式保持磁盘驱动器跳动,则这不一定是快速操作。 如果您不介意偶尔出现误报,请仅选择它。 我个人在工作站上的时间从不低于 10 秒,这是在 Hard Knocks 学校学到的。 服务器类机器 20 秒是安全的。

我意识到这是一个老问题,但它从未得到解决。 这是我的解决方法。

Dim wmiScope As New Management.ManagementScope("\\" & HOST_COMPUTER_HERE & "\root\cimv2")
Dim exception As Exception = Nothing
Dim timeRan As Integer = 0
Dim wmiThread As Threading.Thread = New Threading.Thread(Sub() Wmi_Connect(wmiScope))
    wmiThread.Start()
    While wmiThread.ThreadState = Threading.ThreadState.Running
        Threading.Thread.Sleep(1000)
        timeRan += 1000
'WmiThreadTimeout is a global variable set to 10,000 miliseconds.
            If timeRan >= WmiThreadTimeout Then
                wmiThread = Nothing
                    exception = New Exception(HostName & " could not be connected to within the timeout period.")
                End If
                Exit While
            End If
        End While

这是线程。

Private Sub Wmi_Connect(ByRef wmiScope As Management.ManagementScope)
    Try
        wmiScope.Connect()
    Catch ex As System.Runtime.InteropServices.COMException
    End Try
End Sub

正如我所说,这是一种解决方法。 它不会杀死线程,只是阻止它阻塞。 (我确实意识到将 Thread 对象设置为Nothing不会杀死线程。)

这有效。 在 Task.Wait 行中更改超时。 它将在 5 秒后停止尝试连接,您仍然会收到 RPC 连接异常

    public static bool Connect(string pc)
    {
        var task = new Task<bool>(() =>
        {
            try
            {
                ManagementScope scope = new ManagementScope($"\\\\{pc}\\root\\cimv2");

                scope.Connect();

                return scope.IsConnected;
            }
            catch (Exception ex)
            {
                //Log ex
                return false;
            }
        });

        task.Start();

        return task.Wait(5000) && task.Result;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM