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

本文关键字:WMI 超时 时间 RPC 服务器 设置 | 更新日期: 2023-09-27 18:17:55

我有以下代码检查远程计算机上的服务状态。问题是,如果无法找到远程计算机(它已经关闭或其他),那么ManagementObjectSearcher.Get()方法需要20秒才能抛出"RPC服务器不可用"的错误。在服务器不可用的情况下,我想明确地声明我只希望它尝试很短的一段时间(比如3秒)。我遵循了post 这里,但它声明在ManagementObjectSearcher上使用Timeout选项,但我的代码似乎忽略了该值(因为它声明它与集合无关)。在这些选项中,我是否忽略了什么?我试过使用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)
        {
        }
    }

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

是的,不是那个。您需要设置ConnectionOptions。超时:

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

在我测试时运行良好。

请记住,3秒是低端,如果一段时间没有查询请求,服务器可能不得不将大量代码交换到RAM中来处理请求。如果服务器以其他方式保持磁盘驱动器的跳动,那么这就不一定是一个快速的操作。如果你不介意偶尔的假警报,就选择它。我个人从来不会在工作站上低于10秒,这是我在Hard Knocks School学到的。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

正如我所说的,这是一种变通方法。它不会杀死线程,只是阻止它阻塞。(我意识到设置线程对象为Nothing不会杀死线程。)

可以。在任务中更改超时时间。等线。它将在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;
    }