web-dev-qa-db-fra.com

Powershell - Échec de la connexion de test en raison d'un manque de ressources

La connexion de test échoue par intermittence avec une erreur de manque de ressources:

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

Par conséquent, ce n'est pas fiable et assez inutile lorsque vous devez tester une liste d'ordinateurs en boucle. Existe-t-il un correctif, une alternative ou une solution de contournement pour obtenir cette fonctionnalité de manière fiable?

C'est ma solution actuelle, mais elle n'est toujours pas suffisamment fiable (parfois ils échouent encore 5 fois de suite) et cela prend une éternité à cause de tous les retards et tentatives.

$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}
}

Un ping normal (ping.exe) fonctionne à chaque fois, donc s'il existe un bon moyen d'analyser cela avec PowerShell (hôte vers le haut ou vers le bas, quelle IP répond), cela semble être la solution idéale, mais j'ai juste besoin de quelque chose qui fonctionne, donc je suis ouvert aux idées.

16
cscracker

Dans les versions plus récentes de PowerShell, le -Quiet paramètre sur Test-Connection semble toujours renvoyer True ou False. Cela ne semblait pas fonctionner de manière cohérente sur les anciennes versions, mais soit je fais quelque chose de différent maintenant, soit ils l'ont amélioré:

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

Cependant, je ne l'ai pas testé récemment lorsque le réseau est tout simplement indisponible.


Ancienne réponse:

Test-Connection ne répond pas bien lorsque DNS ne répond pas avec une adresse ou lorsque le réseau n'est pas disponible. Autrement dit, si l'applet de commande décide qu'elle ne peut pas envoyer de ping du tout, elle génère des erreurs désagréables qui sont difficiles à piéger ou à ignorer. Test-Connection n'est utile que lorsque vous pouvez garantir que DNS résoudra le nom en une adresse et que le réseau sera toujours présent.

J'ai tendance à utiliser des pings WMI:

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

Ou Pings CIM:

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

Les deux sont fondamentalement les mêmes, mais renvoient des formats légèrement différents pour les choses. Le principal inconvénient ici est que vous devez résoudre le code d'état vous-même:

$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];

Alternativement, j'ai également utilisé des Pings .Net comme @BenH, qui fait beaucoup de travail pour vous. Il y avait une raison pour laquelle j'ai cessé de les utiliser en faveur de WMI et CIM, mais je ne me souviens plus de cette raison.

11
Bacon Bits

Je préfère utiliser la classe . Net Ping plutôt que Test-Connection

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

Notez que la méthode Send peut prendre des paramètres supplémentaires si vous devez définir TTL/Fragmentation. Le délai d'attente est également en millisecondes, avec juste $ name, le délai d'attente est, je pense, de 5 secondes, ce qui est généralement trop long.

12
BenH

L'assistant IP Windows définit l'erreur IP_REQ_TIMED_OUT à la valeur 11010, qui est la même que l'erreur système Windows WSA_QOS_ADMISSION_FAILURE 11010 "Erreur due au manque de ressources". il est donc probable que ce qui a effectivement été reçu dans le cas en question était une erreur de dépassement de délai et simplement interprété à tort comme un "manque de ressources".

7
wtom