≡ Menu

Powershell# Get-WMIObject is taking long time to query

System administrators depend a lot on WMI objects to query various information from local or remote computers. That means if any of the WMI query is taking long time or never ending, the automatons placed by System administrator may fail. I ran into same situation yesterday. Query against a WMI Class(given by third party application) is taking very long to execute and never ending. This is resulting in my scripts to halt at that computer for very long and not proceeding further. This is a big problem and I feel the automation should handle such cases as well. Otherwise you will be under impression that script is running fine(if you schedule it somewhere) but it is actually not. You will not realize this until someone reports a problem or you yourself identify the problem by manually running the script.

Well, what is the fix now? Can Get-WMIObject support a timeout parameter. No, I couldn’t find any such option. But the dotnet name space(System.Management)  has this facility. I wrote a wrapper function that works on top of Dotnet classes to query the WMI classes of remote computer. This function takes 4 parameters. (1) ComputerName (2) Class (3) NameSpace and (4)TimeOutInSeconds. These parameters are self descriptive so need to explain much.

CODE:

Function Get-WmiObjectCustom{            
[cmdletbinding()]            
param(            
 [string]$ComputerName = $env:ComputerName,            
 [string]$NameSpace = "root\cimv2",            
 [int]$TimeoutInseconds = 60,            
 [string]$Class            
)            

try {            
 $ConnectionOptions = new-object System.Management.ConnectionOptions            
 $EnumerationOptions = new-object System.Management.EnumerationOptions            
 $timeoutseconds = new-timespan -seconds $timeoutInSeconds            
 $EnumerationOptions.set_timeout($timeoutseconds)            
 $assembledpath = "\\{0}\{1}" -f $ComputerName, $NameSpace            
 $Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions            
 $Scope.Connect()            
 $querystring = "SELECT * FROM {0}" -f $class            
 $query = new-object System.Management.ObjectQuery $querystring            
 $searcher = new-object System.Management.ManagementObjectSearcher            
 $searcher.set_options($EnumerationOptions)            
 $searcher.Query = $querystring            
 $searcher.Scope = $Scope            
 $result = $searcher.get()            
} catch {            
 Throw $_            
}            
return $result            
}

Usage:

Get-WMIObjectCustom -Class Win32_ComputerSystem -ComputerName PC1 -TimeoutInSeconds 20

I found this approach organically in MSDN blog and modified the code to make it as advanced function so that it can support error handling better. Also modified a few pieces of code to make it look better.

Happy learning

{ 4 comments… add one }
  • Signal15 October 14, 2014, 6:56 pm

    Greetings! I’m seeing an average of 21 seconds for the code to complete, even when specifying a 2 second timeout….

    PS E:\PS\Test> Get-WMIcustom -Class Win32_ComputerSystem -ComputerName server01 -TimeoutInSeconds 2
    Exception calling “Connect” with “0” argument(s): “The RPC server is unavailable. (Exception from
    HRESULT: 0x800706BA)”
    At line:19 char:16
    + $Scope.Connect <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

  • Sitaram Pamarthi October 18, 2014, 7:47 pm

    Have you used it correctly? Get-WmiObjectCustom is the name of the function but your code shows somethign different.

  • Kevin Kitchen February 19, 2016, 4:47 am

    This is very useful for machines inside the same domain you are querying. How would I insert credentials into this for machines in different domains?

    • Wintel Rocks February 24, 2016, 8:52 pm

      Kevin, do you want to pass the alternate credentials to Get-WMIObject or this custom function?

Leave a Comment