I have the following code that checks the status of a service on a remote computer. The problem is that if the remote computer can't be found (it's down or something), then the ManagementObjectSearcher.Get()
method takes 20 seconds to throw an error of "The RPC Server Is Unavailable". In cases where the server is unavailable, I want to explicitly state that I only want it to try for a short period of time (like 3 seconds). I have followed the post here, but it states to use the Timeout option on ManagementObjectSearcher, but my code seems to ignore that value (as it states it's not relevant on collections). Is there something I'm overlooking on these options? I have tried using the ReturnImmediatly
property as well to no avail.
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)
{
}
}
Yes, not that one. You want to set the ConnectionOptions.Timeout:
var managementScope = new ManagementScope(...);
managementScope.Options.Timeout = TimeSpan.FromSeconds(3);
Worked well when I tested it.
Do keep in mind that 3 seconds is on the low end, the server may well have to swap a lot of code into RAM to handle the request if it hasn't been queried for a while. That's not necessarily a speedy operation if the server is otherwise keeping the disk drive hoppin'. Only pick it if you don't mind the occasional false alarm. I personally never go below 10 seconds on a workstation, learned in the School of Hard Knocks. 20 seconds for a server class machine is safe.
I realize this is an old question, but it never got resolved. This is my workaround.
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
Here's the thread.
Private Sub Wmi_Connect(ByRef wmiScope As Management.ManagementScope)
Try
wmiScope.Connect()
Catch ex As System.Runtime.InteropServices.COMException
End Try
End Sub
As I said, it's a workaround. It doesn't kill the thread, just stops it from blocking. (I do realize setting the Thread object to Nothing
doesn't kill the thread.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With