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
Comments on this entry are closed.
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
Have you used it correctly? Get-WmiObjectCustom is the name of the function but your code shows somethign different.
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?
Kevin, do you want to pass the alternate credentials to Get-WMIObject or this custom function?
I don’t think the timeout value actuall does what you expect it to. It certainly doesn’t seem have any impact RPC call timeouts when doing WMI queries. Read here: https://msdn.microsoft.com/en-us/library/system.management.managementoptions.timeout.aspx
Have you tried it and not working?
I’m running a test case with a wmi call on a server that I do not have creds on with this function and the timeout is not affected, I still see a 20 second wait until it errors out. I still haven’t found a good timeout function addition to regular WMI (thanks Microsoft 😉
Amazing script, thank you so much !