Timeout Get-WMIObject cmdlet

17,322

Solution 1

The only two solutions I've seen for this problem are:

  1. Run the queries as background jobs and put a timer on them, then stop/remove the jobs that run too long.

  2. Fix your servers.

Solution 2

You could try the get-wmiCustom function, posted here. Wouldn't it be nice if get-wmiObject had a timeout parameter? Let's upvote this thing.

Solution 3

I've modified Daniel Muscetta's Get-WmiCustom to also support passing credentials.

I know this post is a little old, hopefully this helps someone else.

# Define modified custom get-wmiobject for timeout with credential from http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx
Function Get-WmiCustom([string]$Class,[string]$ComputerName,[string]$Namespace = "root\cimv2",[int]$Timeout=15, [pscredential]$Credential) 
{ 
    $ConnectionOptions = new-object System.Management.ConnectionOptions
    $EnumerationOptions = new-object System.Management.EnumerationOptions

    if($Credential){
        $ConnectionOptions.Username = $Credential.UserName;
        $ConnectionOptions.SecurePassword = $Credential.Password;
    }


    $timeoutseconds = new-timespan -seconds $timeout 
    $EnumerationOptions.set_timeout($timeoutseconds)

    $assembledpath = "\\$Computername\$Namespace"
    #write-host $assembledpath -foregroundcolor yellow

    $Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions 
    $Scope.Connect()

    $querystring = "SELECT * FROM " + $class 
    #write-host $querystring

    $query = new-object System.Management.ObjectQuery $querystring 
    $searcher = new-object System.Management.ManagementObjectSearcher 
    $searcher.set_options($EnumerationOptions) 
    $searcher.Query = $querystring 
    $searcher.Scope = $Scope

    trap { $_ } $result = $searcher.get()

    return $result 
}

Solution 4

Glad my Get-WmiCustom function here http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx is useful.

Solution 5

when creating the job using get-wmiobject assign that job to a variable, then that variable can be piped into get-job for status or receive-job for results

$ThisJob = start-job -scriptblock {param ($Target) Get-WmiObject -Class Win32_Service -ComputerName $Target -AsJob} -ArgumentList $server
$Timer = [System.Diagnostics.Stopwatch]::StartNew()
While ($ThisJob | Get-Job | where {$_.State -imatch "Running"}){
    If ($Timer.Elapsed.Seconds -ge 5) {
        echo "five seconds has passed, removing"
        $ThisJob | Get-Job | Remove-Job -Force
        } # end if
    echo "still running"
    Start-Sleep -Seconds 3
    } # end while

$Results = $ThisJob | where {$_.State -inotmatch "failed"} | receive-job
$Timer.Stop | out-null
Share:
17,322

Related videos on Youtube

Sune
Author by

Sune

If isn't broke, break it and then fix it.

Updated on June 04, 2022

Comments

  • Sune
    Sune almost 2 years

    I run a script which performs many WMI-querys - but the cmdlet hangs if the server doesn't answer.. Is there any way I can make this (or any other cmndlet for that matter) timeout and exit if X seconds has passed?

    Edit

    Thanks to a tip from mjolinor the solution is to run this as -asjob and set a timeout in a while loop. But this is run from within a job already (started with Start-Job). So how do I know I am controlling the correct job?

    This is my code from inside my already started job:

    Get-WmiObject Win32_Service -ComputerName $server -AsJob
    
    $Complete = Get-date
    
    While (Get-Job -State Running){
        If ($(New-TimeSpan $Complete $(Get-Date)).totalseconds -ge 5) {
            echo "five seconds has passed, removing"
            Get-Job  | Remove-Job -Force
        }
        echo "still running"
        Start-Sleep -Seconds 3
    }
    

    PS: My jobs started with Start-Jobs are already taken care of..

  • Sune
    Sune about 12 years
    Thanks! I am running this already in a job (with start-job -scriptpath). Should I still do -asjob from within a start-job?
  • mjolinor
    mjolinor about 12 years
    I don't see nesting jobs as being any help. For the timer to work you need to run one job per server. This will add a couple of seconds of overhead to each one to create the job, but you can run multiple jobs at once. You'll need to script a process of keeping x number of jobs running at once, one for each server, and then receiving or canceling the jobs as they finish or their ET gets too long, then removing that job and starting up a new one from the next server in the list.
  • Sune
    Sune about 12 years
    The get-wmiobject query is just one of many things I do in my job, but the job hangs if get-wmiobject doesn't answer in proper time.. I will try to do a get-wmiobject -asjob and wait until the job is finished to continue. Maybe not the best practice but I see no other way.
  • noam
    noam about 11 years
    It is very useful. Thank you for making that.