Powershell - Test-Connection failed due to lack of resources
Asked Answered
E

6

27

Test-connection intermittently fails with a lack of resources error:

test-connection : Testing connection to computer 'SOMESERVER' failed: Error due to lack of resources
At line:1 char:45
+ ... ($server in $ServersNonProd.Name) { test-connection $server -Count 1}
+                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (SOMESERVER:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand

As a result, it's not reliable and fairly useless when you need to test a list of computers in a loop. Is there a fix, alternative, or workaround to get this functionality reliably?

This is my current solution, but it's still not sufficiently reliable (sometimes they still fail 5 times in a row) and it takes forever because of all the delays and retries.

$Servers = Import-CSV -Path C:\Temp\Servers.csv

$result = foreach ($Name in $Servers.FQDN) {
    $IP = $null
    if ( Resolve-DNSName $Name -ErrorAction SilentlyContinue ) {
        $IP = (Test-Connection -Count 1 -ComputerName $Name -ErrorAction SilentlyContinue).IPv4Address
        if ( $IP -eq $null ) {
            Start-Sleep -Milliseconds 100
            $IP = (Test-Connection -Count 1 -ComputerName $Name -ErrorAction SilentlyContinue).IPv4Address
        }
        if ( $IP -eq $null ) {
            Start-Sleep -Milliseconds 200
            $IP = (Test-Connection -Count 1 -ComputerName $Name -ErrorAction SilentlyContinue).IPv4Address
        }
        if ( $IP -eq $null ) {
            Start-Sleep -Milliseconds 300
            $IP = (Test-Connection -Count 1 -ComputerName $Name -ErrorAction SilentlyContinue).IPv4Address
        }
        if ( $IP -eq $null ) {
            Start-Sleep -Milliseconds 400
            $IP = (Test-Connection -Count 1 -ComputerName $Name -ErrorAction SilentlyContinue).IPv4Address
        }
    }
    new-object psobject -Property @{FQDN = $Name; "IP Address" = $IP}
}

A normal ping (ping.exe) works every time, so if there's a good way to parse that with powershell (host up or down, what IP is responding), that seems like the ideal solution, but I just need something that works, so I'm open to ideas.

Epistrophe answered 21/12, 2016 at 16:30 Comment(4)
well, that looks pretty weird, so to work around that you can implement do-while loop, but I suggest you fight the root cause. Like what did you try to fix it? /sfc scannow at least? anything? Upgrade to PS5?Onepiece
Have actually seen this before but was never able to locate a fix, although iirc a reboot would generally correct it(I could be wrong, has been over a year) Also what version of PS are you running? seem to remember the issue only impacting PSv2(again, could be misremembering)Supen
How about using -Quiet or -ErrorAction SilentlyContinue or both? This may be caused by a WMI failure on the remote host. And -Count 1 is not always reliable. My usual line: if(Test-Connection $host -Quiet -Count 2 -EA 0) { #... }, works like a charm.Initiation
I'm using Powershell 5 on Windows 10 most often, but it occurs on Powershell 4 on 2012 R2 too. I haven't extensively tested other versions beyond those. I can silently ignore the errors but the errors occur both on hosts that are up and ones that aren't, so the results are inaccurate either way. Restarting Powershell and restarting the computer don't fix it (or don't fix it for long), and are not viable options.Epistrophe
A
21

In newer versions of PowerShell, the -Quiet parameter on Test-Connection does seem to always return either True or False. It didn't seem to work consistently on older versions, but either I'm doing something differently now or they've improved it:

$Ping = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet

I haven't tested it recently when the network is simply unavailable, however.


Older answer:

Test-Connection doesn't respond well when DNS doesn't respond with an address or when the network is unavailable. That is, if the cmdlet decides it can't send the ping at all, it errors in unpleasant ways that are difficult to trap or ignore. Test-Connection is only useful, then, when you can guarantee that DNS will resolve the name to an address, and that the network will always be present.

I tend to use CIM Pings (Powershell v3+):

$Ping2 = Get-CimInstance -ClassName Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000";

Or WMI pings (Powershell v1 or v2):

$Ping = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000";

Either of which are basically the same, but return slightly different formats for things. Note that Get-WmiObject is not available at all beginning in Powershell v6 because Get-CimInstance was designed to supersede it.

The main disadvantage here is that you have to resolve the status code yourself:

$StatusCodes = @{
    [uint32]0     = 'Success';
    [uint32]11001 = 'Buffer Too Small';
    [uint32]11002 = 'Destination Net Unreachable';
    [uint32]11003 = 'Destination Host Unreachable';
    [uint32]11004 = 'Destination Protocol Unreachable';
    [uint32]11005 = 'Destination Port Unreachable';
    [uint32]11006 = 'No Resources';
    [uint32]11007 = 'Bad Option';
    [uint32]11008 = 'Hardware Error';
    [uint32]11009 = 'Packet Too Big';
    [uint32]11010 = 'Request Timed Out';
    [uint32]11011 = 'Bad Request';
    [uint32]11012 = 'Bad Route';
    [uint32]11013 = 'TimeToLive Expired Transit';
    [uint32]11014 = 'TimeToLive Expired Reassembly';
    [uint32]11015 = 'Parameter Problem';
    [uint32]11016 = 'Source Quench';
    [uint32]11017 = 'Option Too Big';
    [uint32]11018 = 'Bad Destination';
    [uint32]11032 = 'Negotiating IPSEC';
    [uint32]11050 = 'General Failure'
    };
$StatusCodes[$Ping.StatusCode];
$StatusCodes[$Ping2.StatusCode];

Alternately, I've used .Net Pings like @BenH described, too, which does a lot of that work for you. There was a reason I stopped using them in favor of WMI and CIM, but I can no longer remember what that reason was.

Asbestos answered 21/12, 2016 at 17:15 Comment(4)
It's likely due to the fact that the .NET pings don't return verbose errors, it appears to be mostly Success or TimedOut, though I haven't tested with a flaky network to see if it returns some of the other error codes.Duky
@Duky Yes, most of those network states are very difficult to recreate easily.Asbestos
The Get-WmiObject version does not work with IPv6 addresss. According to Microsoft, IPv6 is supported in WMI since Visa. However, using an IP6 addresses produces an error where WMI complains about an invalid : character. Get-CimInstance works as expected for both IPv4 and IPv6.Alidis
I like wmi ping.Colous
S
14

I am partial to using the .Net Ping class rather than Test-Connection

$Timeout = 100
$Ping = New-Object System.Net.NetworkInformation.Ping
$Response = $Ping.Send($Name,$Timeout)
$Response.Status

Note that the Send method can take additional parameters if you need to set TTL/Fragmentation. Also timeout is in milliseconds, with just $name the timeout I think is 5 seconds, which is usually too long.

Sulfur answered 21/12, 2016 at 16:56 Comment(0)
G
12

Windows IP Helper defines IP_REQ_TIMED_OUT error to value 11010 wich is the same as Windows system error WSA_QOS_ADMISSION_FAILURE 11010 'Error due to lack of resources.' so it is likely that what actually received in questioned case was time out error and simply misinterpreted as 'lack of resources'.

Gauldin answered 6/6, 2018 at 15:29 Comment(1)
This makes more sense than a DNS issue, especially when testing against successful and failing IPv4 addressing like 8.8.8.8 and 7.7.7.7 ;)Chemo
K
1

I see this error when (in 5.x anyway) i include -computername in test-connection. remove that and it works. The other thing about using ping vs test-connection, ICMP is blocked by default with the windows firewall where test-connection does the equivalent of the win32_pingstatus command. WMI is not blocked by default. However, if the WMI repository on the system is not healthy (or blocked by fw) it will of course fail.

Kylix answered 1/11, 2021 at 19:34 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewSkindive
M
0

powershell v7 does not suffer from this issue when using test-connection

Mechellemechlin answered 24/6, 2020 at 13:31 Comment(0)
C
0

I'm going to cheat and use powershell 7. Microsoft is always unpingable.

test-connection -count 1 yahoo.com,microsoft.com | select destination,status

Destination     Status
-----------     ------
yahoo.com      Success
microsoft.com TimedOut

Or multi-threaded:

echo yahoo.com microsoft.com | % -parallel { test-connection -count 1 $_ } | 
  select destination,status

Destination     Status
-----------     ------
yahoo.com      Success
microsoft.com TimedOut
,'microsoft.com' * 10 | % -parallel { test-connection -count 1 $_ } | 
  select destination,status

Destination     Status
-----------     ------
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut
microsoft.com TimedOut


# one time takes like 4 seconds
measure-command { ,'microsoft.com' * 10 | % -parallel { test-connection -count 1 $_ } | 
  select destination,status } | % seconds

9
Colous answered 1/2, 2021 at 20:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.