107 votes

Powershell : Comment puis-je empêcher les erreurs d'être affichées dans un script ?

Lorsque mon script PowerShell essaie, par exemple, de créer un objet SQL Server pour un serveur qui n'existe pas ("bla" dans mon cas), PowerShell affiche beaucoup d'erreurs PowerShell en rouge.

Étant donné que mon script vérifie la valeur de $? après de tels appels, et affiche et enregistre les erreurs, je préférerais ne pas avoir les plusieurs lignes d'erreurs PowerShell affichées également.

Comment puis-je les désactiver pour mon script?

155voto

JNK Points 32743

Vous avez quelques options. Les plus simples supposent l'utilisation des paramètres ErrorAction.

-Erroraction est un paramètre universel pour toutes les cmdlets. Si vous souhaitez ignorer des commandes spéciales, vous pouvez utiliser -erroraction 'silentlycontinue' qui ignorera essentiellement tous les messages d'erreur générés par cette commande. Vous pouvez également utiliser la valeur Ignore (dans PowerShell 3+):

Contrairement à SilentlyContinue, Ignore n'ajoute pas le message d'erreur à la variable automatique $Error.

Si vous souhaitez ignorer toutes les erreurs dans un script, vous pouvez utiliser la variable système $ErrorActionPreference et faire la même chose: $ErrorActionPreference= 'silentlycontinue'

Consultez about_CommonParameters pour plus d'informations sur -ErrorAction. Consultez about_preference_variables pour plus d'informations sur $ErrorActionPreference.

0 votes

Est-ce que vous avez besoin de guillemets simples dans -erroraction 'silentlycontinue'? IntelliSense montre des options et n'ajoute pas de guillemet simple.

1 votes

Si le format ci-dessus ne fonctionne pas pour vous, référez-vous au lien fourni ci-dessus. J'ai dû formater comme -ErrorAction:SilentlyContinue dans PS 5.1. J'appelais mon cmdlet depuis un fichier batch donc je ne sais pas si ça change quelque chose. Mais c'est une bonne info quand vous savez qu'une erreur acceptable peut être envoyée.

0 votes

--rm .\Windows.old\ -Force -Recurse -Verbose -ErrorAction SilentlyContinue -WarningAction SilentlyContinue

21voto

JPBlanc Points 26156

Windows PowerShell fournit deux mécanismes pour signaler des erreurs : un mécanisme pour les erreurs terminales et un autre mécanisme pour les erreurs non-terminales.

Le code des CmdLets internes peut appeler une méthode ThrowTerminatingError lorsqu'une erreur se produit et ne permet pas ou ne devrait pas permettre au cmdlet de continuer à traiter ses objets d'entrée. Le rédacteur de script peut ensuite utiliser des exceptions pour intercepter ces erreurs.

EX :

try
{
  Votre code de base de données
}
catch
{
  Rapport d'erreurs/journalisation
}

Le code des CmdLets internes peut appeler une méthode WriteError pour signaler des erreurs non-terminales lorsque le cmdlet peut continuer à traiter les objets d'entrée. Le rédacteur de script peut ensuite utiliser l'option -ErrorAction pour masquer les messages, ou utiliser $ErrorActionPreference pour configurer le comportement global du script.

7voto

D-W Points 79

J'ai eu un problème similaire en essayant de résoudre des noms d'hôte en utilisant [system.net.dns]. Si l'IP n'était pas résolue, .Net lançait une erreur terminale. Pour éviter l'erreur terminale et conserver le contrôle de la sortie, j'ai créé une fonction en utilisant TRAP.

Par exemple

Function Get-IP 
{PARAM   ([string]$HostName="")
PROCESS {TRAP 
             {"" ;continue} 
             [system.net.dns]::gethostaddresses($HostName)
        }
}

7voto

jpmc26 Points 3364

Vous vous écartez complètement de la voie ici. Supprimer les erreurs n'est presque jamais une bonne idée, et vérifier manuellement $? explicitement après chaque commande individuelle est extrêmement fastidieux et facile à oublier de le faire (source d'erreurs). Ne vous mettez pas en situation de commettre facilement une erreur. Si vous obtenez beaucoup et beaucoup de rouge, cela signifie que votre script a continué alors qu'il aurait dû s'arrêter. Il ne peut plus effectuer un travail utile si la plupart de ses commandes échouent. Continuer un programme lorsque lui et le système se trouvent dans un état inconnu aura des conséquences inconnues; vous pourriez facilement laisser le système dans un état corrompu.

La solution correcte est d'arrêter l'algorithme à la première erreur. Ce principe s'appelle "échouer vite," et PowerShell possède un mécanisme intégré pour activer ce comportement. Il s'agit du paramètre appelé préférence de gestion des erreurs, et le configurer avec le niveau le plus élevé fera en sorte que votre script (ainsi que les ports enfant s'ils ne le remplacent pas) se comporte de cette manière :

$ErrorActionPreference = 'Stop'

Cela produira un joli message d'erreur pour que vous puissiez le consommer et empêchera les commandes suivantes d'être exécutées la première fois qu'un problème survient, sans avoir à vérifier $? chaque fois que vous exécutez une commande. Cela rend le code beaucoup plus simple et fiable. Je le mets au début de chaque script que j'écris, et vous devriez presque certainement en faire de même.

Dans les cas rares où vous pouvez être absolument certain qu'il est logique de permettre au script de continuer, vous pouvez utiliser l'un des deux mécanismes suivants :

  • catch : C'est le mécanisme le meilleur et le plus flexible. Vous pouvez envelopper un bloc try/catch autour de plusieurs commandes, permettant à la première erreur d'arrêter la séquence et de passer dans le gestionnaire où vous pouvez le consigner et ensuite récupérer ou le relancer pour faire remonter davantage l'erreur. Vous pouvez également limiter le catch à des erreurs spécifiques, ce qui signifie qu'il ne sera invoqué que dans des situations spécifiques que vous avez anticipées plutôt que pour n'importe quelle erreur. (Par exemple, échouer à créer un fichier car il existe déjà justifie une réponse différente de celle d'un échec de sécurité.)
  • Le commun paramètre -ErrorAction : Ce paramètre modifie la gestion des erreurs pour un seul appel de fonction, mais vous ne pouvez pas le limiter à des types d'erreurs spécifiques. Vous ne devriez l'utiliser que si vous pouvez être certain que le script peut continuer en cas d'erreur quelconque, pas seulement celles que vous pouvez anticiper.

Dans votre cas, vous voulez probablement un grand bloc try/catch autour de l'ensemble de votre programme. Ensuite, votre processus s'arrêtera à la première erreur et le bloc catch peut la consigner avant de sortir. Cela supprimera beaucoup de code en double de votre programme en plus d'améliorer votre fichier journal et votre sortie du terminal et rendra votre programme moins susceptible de causer des problèmes.

À noter que cela ne gère pas le cas des échecs d'exécutables externes (code de sortie non nul, conventionnellement), donc vous devez toujours vérifier $LASTEXITCODE si vous invoquez un quelconque. Malgré cette limitation, le paramètre permet cependant d'économiser beaucoup de code et d'effort.

Fiabilité supplémentaire

Vous voudrez peut-être également envisager d'utiliser le mode strict :

Set-StrictMode -Version Latest

Cela empêche PowerShell de continuer en silence lorsque vous utilisez une variable inexistante et dans d'autres situations étranges. (Consultez le paramètre -Version pour plus de détails sur ce qu'il restreint.)

Combiner ces deux paramètres rend PowerShell beaucoup plus un langage de "échouer vite", ce qui facilite énormément la programmation en lui.

1 votes

Vous prétendez que cela rend les choses plus fiables mais dans le cas de toute automatisation, cela fait l'inverse. Parfois, il y a des scripts qui doivent s'exécuter indépendamment de l'existence d'une erreur avec une commande précédente et il est beaucoup plus facile de distribuer un seul script PowerShell que un par action requise. Avec votre solution, si un fichier qui doit être supprimé au démarrage n'est pas présent (à cause de Windows), alors aucune des commandes ultérieures dans ce script ne sera exécutée malgré le système étant dans l'état requis. Félicitations, vous avez maintenant un script cassé s'exécutant à distance avec des erreurs qui ne sont pas poussées vers un fichier journal.

0 votes

@TheHitchenator Et bien plus souvent, le script devrait s'arrêter avant de produire un résultat inattendu, qui pourrait endommager le système de quelque manière que ce soit, invalidant complètement votre point. Si vous savez que vous voulez qu'il continue même en cas d'erreur, j'ai expliqué comment faire cela.

0 votes

@TheHitchenator De plus, l'OP s'assure déjà que les erreurs sont détectées et traitées. Faire cela manuellement pour chaque commande individuelle n'est pas plus fiable que de laisser PowerShell le faire pour vous. Tu as complètement manqué le point.

5voto

skeetastax Points 383

Vous pouvez également ajouter 2>$null à votre commande.

Exemple:

$rec = Resolve-DnsName $fqdn -Server $dns 2>$null

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X