To change/tweak the WMI timeout value, you can instantiate a WMI or WMI searcher object and set its timeout property, which is a time span object. In this informational top example, it's done through the PSBase member set. Notice the empty string after the [wmi] type accelerator in the example directly below. The WMI timeout is only changed for that specific object instance, so this is basically useless other than for the sake of enlightenment.
The example further down uses a [WmiSearcher] object and sets its properties. This top example is for informational purposes only. Look at the code below to see the real deal immediately.Now the bad news: During testing I discovered that the clients that "get stuck" still get stuck... And the timeout appears only to be in effect if WMI is working properly on the target computer. It appears to be limiting the time an actual query takes, not when to abort the attempt. Now that makes it a lot less useful; I will have to dig deeper to see if this broken behavior is at all remediable. Note made 2022-01-25: Runspaces allow you to set a timeout, as do PowerShell jobs. See Get-Help Start-Job.
Also consider checking out the PowerShell Get-WmiObject Wrapper script here. It's pretty darn useful. It uses runspaces to handle the timeouts.PS E:\> $wmi = [wmi]'' PS E:\> $wmi.PSBase.Options.Timeout = '0:0:5'
Here "0:0:5" is cast to a time span value, which in this case is equivalent to 5 seconds (hours:minutes:seconds). You can look at the timeout property you just set like this:
PS E:\> $wmi.PSBase.Options.Timeout Days : 0 Hours : 0 Minutes : 0 Seconds : 5 Milliseconds : 0 Ticks : 50000000 TotalDays : 5,78703703703704E-05 TotalHours : 0,00138888888888889 TotalMinutes : 0,0833333333333333 TotalSeconds : 5 TotalMilliseconds : 5000
To inspect the various properties, use:
$wmi.PSBase | Get-Member
... and
$wmi.PSBase.Options | Get-Member
# Utility function making lists "less quoty" function ql { $args } # A list of computers to process. $Computers = ql win7esxi ubuntu64esxi silverstone winxpesxi 2008r2esxi localhost # The purpose here is to have clean output to the console (or redirected to a file). $Computers | ForEach-Object { # This is needed for the error handling in the catch block where $_ gets # set to the last error rather than the computer name. $Computer = $_ # Since certain WMI errors are terminating, we need a try/catch statement. try { # Here we specify the WMI query $Searcher = [WmiSearcher]'SELECT * FROM Win32_ComputerSystem' # This is where we set the timeout to 5 seconds. $Searcher.Options.TimeOut = "0:0:5" # Create necessary objects, specify a scope and namespace for the remote computer (or localhost or '.'), # then set the scope on the WMISearcher object, which is usually "\\computername\root\cimv2". $ConnectionOptions = New-Object Management.ConnectionOptions $ManagementScope = New-Object Management.ManagementScope("\\${Computer}\root\cimv2", $ConnectionOptions) $Searcher.Scope = $ManagementScope # Perform the query and retrieve the desired property, and expand it to a # string with Select -ExpandProperty. $MemSize = $Searcher.Get() | Select-Object -ExpandProperty TotalPhysicalMemory # Use this check for if there's a non-terminating error. if ($?) { $MemSizeGB = ($MemSize/1GB).ToString('N') Write-Output "${computer}: $MemSizeGB" } # If a non-terminating error occurs, we get here, but I think all errors are terminating with $searcher.Get() ... else { Write-Output "${Computer}: Error: $($Error[0])" } } # If WMI has a terminating error, we get here. catch { Write-Output "${Computer}: Error (terminating): $($Error[0])" } }
You can use PowerShell jobs, which can be combined with a lowered, or increased, WMI timeout value. You can also check out another non-generic example using jobs, in this article about getting computer models in a domain.
Note made on 2022-01-25: This article is ... "weird". I'm not 100 % sure my test environment was representative when I was researching this. The article gets some minor traffic, which tells me it helps some people with something. For a way to set a thread timeout using efficient runspaces, see this article. These runspaces are compatible with PowerShell version 2 and up. With PowerShell 7 / PowerShell Core came Foreach-Object -Parallel, which you may want to research.
PS C:\prog\Powershell> .\Wmi-Timeout-Example-New.ps1 win7esxi: 2.00 ubuntu64esxi: Error (terminating): Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" silverstone: Error (terminating): Exception calling "Get" with "0" argument(s): "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))" winxpesxi: 0.50 2008r2esxi: 2.00 localhost: 2.00
PS C:\prog\Powershell> .\Wmi-Timeout-Example-New.ps1 | Select-String -NotMatch 'error' > memsize.txt PS C:\prog\Powershell> type .\memsize.txt win7esxi: 2.00 winxpesxi: 0.50 2008r2esxi: 2.00 localhost: 2.00
For better validation, and not excluding unwanted lines that for some reason contain the string "error", we can use a regular expression (read more about regular expressions here) for more control. This should be sufficient in most cases:
PS C:\prog\Powershell> .\Wmi-Timeout-Example-New.ps1 | Select-String -NotMatch '^[^:]+:\s*Error' > memsize.txt PS C:\prog\Powershell> type .\memsize.txt win7esxi: 2.00 winxpesxi: 0.50 2008r2esxi: 2.00 localhost: 2.00
The regular expression used above is "^[^:]+:\s*Error", which means: Start at the beginning, match one or more non-colon characters, as many as you can, match a literal colon (":"), possibly whitespace ("*" is a quantifier and indicates zero or more, always matches) and it's finally followed by the literal string "Error".
Powershell Windows Wmi All CategoriesMinimum cookies is the standard setting. This website uses Google Analytics and Google Ads, and these products may set cookies. By continuing to use this website, you accept this.