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