Wednesday, September 2, 2015

PowerShell – Hanging Get-WmiObject

 

I ran into something that I didn’t know was an issue with Get-WmiObject. I have been using Get-WmiObject for quite sometime so this was a shock to me. I had written a script to grab the description from servers and dump them to a gridview.

I wanted to run this on 1400 servers. Meaning know it was going to take awhile. When I ended up running it, it took too long, actually waaaay to long. The reason? Some of the Get-WmiObject calls were hanging for what ever reason. No problem I thought lets assign the timeout argument to the Get-WmiObject? Where is the timeout argument? ??? After a bit of searching and reading I learned there is no way to set a timeout to the Get-WmiObject commandlet.

After some more reading I learned that the best way to handing this is to setup the Get-WmiObject as a Job. The job can handle the Get-WmiObject process and if it takes longer than you think it should, kill the job and move on.

I don’t have the old way I was running the script but this is the new way.. I tried to comment it as much as I could.

 

    # try this and catch it if it fails

    try {

        # Set the try to stop if it error out

        $ErrorActionPreference = 'Stop'

       

              

        # start the Job and assign it to a variable.. 

 

        # -scriptBlock -- assign the -scriptblock argument to show what to run.. this is where the

        #     get-wmiobject is run. This is encapsualted in {}

 

        # param  -- set the param to pass along the server name from the -ArgumentList to the

        #    Get-WmiObject commandlet

 

        # -ArgumentList pass in the server information.

 

        # | Wait-Job  -Timeout 2 - This tells the job to wait for 2 seconds.

 

        $job = start-job -scriptBlock {param ([string]$server) Get-WmiObject -Class Win32_OperatingSystem -ComputerName $server } -ArgumentList $server | Wait-Job  -Timeout 2

 

        # This dumps out the job information to a variable to use later

        $results = $job | Receive-Job | select Description

       

        # If the Job state is not completed then it was and error, so write out an error for the

        #   try/catch to catch.

        if ($job.state -ne "Completed") {Write-Error "Error"}

       

        # This is the where we put the variables into an array.

        $List += [pscustomobject]@{

        'ComputerName' = $server

        'Description'  = $results.Description

        }

    }

 

    catch {

        #catch if there is an error and if there is write that there was one in the lsit array..

       $List += [pscustomobject]@{

       'ComputerName'         = $server

       'Description' = "Error"

 

       }

    }

 

 

Here is the full script.

 

 

 

#get the list of servers to scan from serverlist.txt

$serverlist = "C:\scripts\computers.txt"

$List = @()

$i = 0

$fileCount = 0

 

#get the count of servers for updates to the user.

 

$fileCount = (Get-Content $serverlist | Measure-Object).Count

 

 

#Loop the server list.

foreach ($server in Get-Content $serverlist) {

 

#increment the number of records proccessed

$i++

 

#Write to the screen whats happening.

Write-Progress -activity "Connecting to server $server" -status "Scanning: $i of $($fileCount)" -percentComplete (($i / $fileCount)  * 100)

 

 

 

 

 

 

 

    # try this and catch it if it fails

    try {

        # Set the try to stop if it error out

        $ErrorActionPreference = 'Stop'

       

              

        # start the Job and assign it to a variable.. 

        # -scriptBlock -- assign the -scriptblock argument to show what to run.. this is where the get-wmiobject is run. This is encapsualted in {}

        # param  -- set the param to pass along the server name from the -ArgumentList to the Get-WmiObject commandlet

        # -ArgumentList pass in the server information.

        # | Wait-Job  -Timeout 2 - This tells the job to wait for 2 seconds.

 

        $job = start-job -scriptBlock {param ([string]$server) Get-WmiObject -Class Win32_OperatingSystem -ComputerName $server } -ArgumentList $server | Wait-Job  -Timeout 2

 

        # This dumps out the job information to a variable to use later

        $results = $job | Receive-Job | select Description

       

        # If the Job state is not completed then it was and error, so write out an error for the try/catch to catch.

        if ($job.state -ne "Completed") {Write-Error "Error"}

       

        # This is the where we put the variables into an array.

        $List += [pscustomobject]@{

        'ComputerName' = $server

        'Description'  = $results.Description

        }

    }

 

    catch {

        #catch if there is an error and if there is write that there was one in the lsit array..

       $List += [pscustomobject]@{

       'ComputerName'         = $server

       'Description' = "Error"

 

       }

    }

 

 

}

 

$List  | Out-GridView

 

 

 

1 comment:

  1. My Admin Journal: Powershell – Hanging Get-Wmiobject >>>>> Download Now

    >>>>> Download Full

    My Admin Journal: Powershell – Hanging Get-Wmiobject >>>>> Download LINK

    >>>>> Download Now

    My Admin Journal: Powershell – Hanging Get-Wmiobject >>>>> Download Full

    >>>>> Download LINK Zj

    ReplyDelete