我有以下代码检查远程计算机上的服务状态。问题是,如果无法找到远程计算机(它已经关闭或者其他东西),那么ManagementObjectSearcher.Get()
方法需要20秒才能抛出错误“#S12; RPC服务器是不可用&#34 ;.在服务器不可用的情况下,我想明确声明我只希望它在短时间内尝试(例如3秒)。我已关注帖子 here ,但它声明在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)
{
}
}
答案 0 :(得分:8)
是的,不是那个。您想要设置ConnectionOptions.Timeout:
var managementScope = new ManagementScope(...);
managementScope.Options.Timeout = TimeSpan.FromSeconds(3);
我测试时工作得很好。
请记住,3秒是在低端,服务器可能必须将大量代码交换到RAM中以处理请求,如果它已经被查询了一段时间。如果服务器另外保持磁盘驱动器跳频,则不一定是快速操作。如果你不注意偶尔的误报,只能选择它。我个人从来没有在工作站上低于10秒,在Hard Knocks学校学习。服务器类机器20秒是安全的。
答案 1 :(得分:2)
我意识到这是一个老问题,但它从未得到解决。这是我的解决方法。
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
不会杀死该线程。)
答案 2 :(得分:0)
这有效。在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;
}