Solved

Set timeout for WMI query

Posted on 2010-08-31
8
1,685 Views
Last Modified: 2013-11-27
I have some code that pings a system. If it's online, it checks what OS is on it. However, some systems randomly have problems with the WMI and will lock up my code. I need a way of setting some sort of at timeout so that it will skip to the next step if it sits for more than 10 seconds.
 
If PingComputer(strcomputer) = True Then
                Dim ooss As Object
                Dim oos
                Dim sos As String
                Dim OSTXT = ""
                Try

                    ooss = GetObject("winmgmts:\\" & strcomputer).InstancesOf("Win32_OperatingSystem")

                    For Each oos In ooss

                        sos = oos.Name
                        Dim sp
                        Dim pos As Integer
                        Dim trimnull
                        pos = InStr(sos, "|")

                        If pos Then
                            trimnull = Microsoft.VisualBasic.Left(sos, pos - 1)
                            sp = oos.ServicePackMajorVersion
                            OSTXT = trimnull & " SP " & sp
                        End If

                    Next

                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
               
            End If

Open in new window

0
Comment
Question by:jcamping
  • 3
  • 3
  • 2
8 Comments
 
LVL 6

Expert Comment

by:apresence
ID: 33570534
WMI depends on DCOM, and there's some registry setting you can use to control the timeout for DCOM calls, but I don't remember it off the top of my head.  Perhaps someone else does.  In the meantime, I'm searching around for it...
0
 

Author Comment

by:jcamping
ID: 33581933
From what I can tell, the DCOM setting you are referring to would have to be set on every machine. I'm just looking for a way to programmatically time out a piece of code after a designated amount of time. It seems like this would be something that would be possible. Is it?
0
 
LVL 41

Expert Comment

by:graye
ID: 33586702
Oddly enough, there isn't a good way to set the DCOM timeout...   WMI *does* have a "dead man switch" to terminate a call if it takes too long.  But that doesn't come into play until after the connection is sucessfully made.
If you're interested in some cool WMI examples, take a look at the downloadable source code at: http://www.emmet-gray.com/Articles/WMI_Intro.htm
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:jcamping
ID: 33592449
OK, so if there is no way to kill the code, is there a way to check to see if WMI is functioning before trying to connect to it?
0
 
LVL 41

Expert Comment

by:graye
ID: 33593049
Nope, not really...  that's a catch 22... you need WMI to be able to determine if WMI is running OK !
I generally do a "ping" first, and then attempt to do a WMI connection.   If it times out, it times out... and I move on to the next one in the list..   For example, during lunch today, I polled about 400 PCs via WMI.  Yeah, sure... some of them didn't answer a ping or didn't respond to a WMI query, but I've only had a lockup about two times in about 10 years of doing this.
0
 
LVL 41

Expert Comment

by:graye
ID: 33593054
... oops, I hit submit too quickly
So, let's concentrate on what's going on that can cause a lockup.  Have you been able to isolate a "test case" where a PC is the cause of the lockup?
0
 
LVL 6

Accepted Solution

by:
apresence earned 500 total points
ID: 33593899
I apologize, I had a major brain lapse when I first looked at your question.  Whenever I see something relating to WMI, I automatically assume VBScript, but I can see now you are working with VB.NET.  That makes things a lot easier...

Create a thread that does the WMI stuff, and wait for it to complete within a certain timeout value. If the timeout is reached, terminate the thread.

Drop the attached code into a module or class, and replace the contents between the Try and Catch statements of DoWMIStuff with the WMI code provided in your question. You can put your output variable in oargs.stroutput, or create additional output variables in the WMIStuffArgs class.

If you're running this test on multiple computers, you can even create several threads at a time so that you can go through your whole list of computers faster.

NOTE: This is NOT the best way to do this if you're trying to create a high-performance application.  A better way is to use the APM (Asynchronous Programming Model) feature of .NET.  But, using this method is a bit more complicated and I'm not sure if it will fit well in the program you are writing/using.

Output of testing the code (uncomment the appropriate line to test):
MAIN   Starting worker thread
THREAD Started with argument: remote_computer
MAIN   Worker thread terminated with exception: System.Exception: foo at ThreadTimeout_VB.Module1.DoWMIStuff(Object state) in C:\LocalWork\Dev\ThreadTimeout_VB\ThreadTimeout_VB\Module1.vb:line 21
MAIN   Application completed

MAIN   Starting worker thread
THREAD Started with argument: remote_computer
MAIN   Timeout waiting for worker thread to complete; Terminating
MAIN   Worker thread terminated
MAIN   Application completed

MAIN   Starting worker thread
THREAD Started with argument: remote_computer
THREAD Completed with success
MAIN   Worker thread terminated with success; Output=[remote_computer_from_thread]
MAIN   Application completed

Class WMIStuffArgs
        Public strcomputer As String
        Public success As Boolean
        Public e As Exception
        Public stroutput As String

        Public Sub New()
            strcomputer = Nothing
            success = False
            e = Nothing
        End Sub
    End Class

    Sub DoWMIStuff(ByVal state As Object)
        Dim oargs As WMIStuffArgs : oargs = state

        Try
            Console.WriteLine("THREAD Started with argument: {0}", oargs.strcomputer)
            '- Note: Uncomment next line to test exception handling
            'Throw New Exception("foo")
            '- Note: Uncomment next line to cause a timeout
            'System.Threading.Thread.Sleep(15000)
            '- Note: Uncomment next line to complete with success
            System.Threading.Thread.Sleep(5000)
            oargs.stroutput = oargs.strcomputer & "_from_thread"
            oargs.success = True
            Console.WriteLine("THREAD Completed with success")
        Catch e As Exception
            oargs.e = e
        End Try
    End Sub

    Sub Main()
        Dim wmiThread As System.Threading.Thread
        Dim wmiArgs As WMIStuffArgs

        wmiThread = New System.Threading.Thread(AddressOf DoWMIStuff)
        wmiArgs = New WMIStuffArgs

        Console.WriteLine("MAIN   Starting worker thread")
        wmiArgs.strcomputer = "remote_computer"
        wmiThread.Start(wmiArgs)

        If (Not wmiThread.Join(10000)) Then
            Console.WriteLine("MAIN   Timeout waiting for worker thread to complete; Terminating")
            wmiThread.Abort()
            Console.WriteLine("MAIN   Worker thread terminated")
        Else
            If (Not (wmiArgs.e Is Nothing)) Then
                Console.WriteLine("MAIN   Worker thread terminated with exception: {0}", wmiArgs.e.ToString)
            ElseIf (wmiArgs.success) Then
                Console.WriteLine("MAIN   Worker thread terminated with success; Output=[{0}]", wmiArgs.stroutput)
            Else
                Console.WriteLine("MAIN   Worker thread terminated with failure")
            End If
        End If

        Console.WriteLine("MAIN   Application completed")
        Console.ReadLine()
    End Sub

Open in new window

0
 

Author Closing Comment

by:jcamping
ID: 33598392
That's awesome. I've looked everywhere for something easy to follow like this! Thanks so much apresence!
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question