Sophie repense au script de l’ancien stagiaire, vu en 5.2 : « Un jour, ce script a planté à 3h du matin parce qu’un serveur de la liste était injoignable. Résultat : les 12 serveurs suivants n’ont jamais été vérifiés, et personne ne l’a su avant le lendemain matin. » Après plusieurs années à écrire des scripts destinés à tourner sans surveillance, la gestion des erreurs est probablement le sujet le plus sous-estimé par les débutants — et celui qui cause le plus d’incidents silencieux en production.
Deux familles d’erreurs à distinguer
PowerShell distingue deux types d’erreurs, dont la différence est essentielle pour comprendre try/catch :
- Erreur terminante : arrête immédiatement l’exécution du script (une exception .NET classique, un accès refusé bloquant)
- Erreur non-terminante : affichée en rouge, mais le script continue à s’exécuter normalement pour la suite
C’est cette seconde catégorie qui piège le plus de débutants : par défaut, la plupart des erreurs de cmdlets (un service introuvable, un serveur injoignable) sont non-terminantes. try/catch ne les intercepte donc pas tant qu’on ne change pas ce comportement, comme on va le voir juste après.
try / catch / finally : intercepter une erreur
try {
Get-Service -Name "ServiceInexistant" -ErrorAction Stop
} catch {
Write-Warning "Erreur rencontrée : $($_.Exception.Message)"
} finally {
Write-Output "Vérification terminée, quel que soit le résultat"
}- Le bloc
trycontient le code à risque - Le bloc
catchne s’exécute que si une erreur terminante survient dans letry - Le bloc
finallys’exécute toujours, erreur ou non — utile pour une action de nettoyage (fermer une connexion, par exemple)
$_ (déjà croisé dans le pipeline en 2.3) représente ici l’objet d’erreur capturé, avec sa propriété Exception.Message qui contient le texte lisible de l’erreur.
Point essentiel, source d’un piège très fréquent : sans
-ErrorAction Stopajouté explicitement à la cmdlet, la plupart des erreurs PowerShell sont non-terminantes par défaut, et le bloccatchne se déclenchera jamais, même en cas d’erreur réelle. C’est probablement la confusion numéro un observée chez les administrateurs qui débutent avectry/catch: ils supposent, à tort, quetryintercepte automatiquement toute erreur affichée en rouge dans la console.
ErrorAction : contrôler le comportement d’une erreur
Le paramètre -ErrorAction, disponible sur la quasi-totalité des cmdlets, permet de forcer leur comportement :
| Valeur | Comportement |
|---|---|
Continue (par défaut) | Affiche l’erreur en rouge, continue l’exécution |
Stop | Transforme l’erreur en erreur terminante, capturable par catch |
SilentlyContinue | Masque l’erreur, continue l’exécution sans rien afficher |
Ignore | Masque l’erreur, sans même l’enregistrer dans $Error |
Get-Service -Name "ServiceInexistant" -ErrorAction SilentlyContinueRetour d’expérience terrain :
SilentlyContinueest extrêmement pratique, mais aussi extrêmement dangereux mal utilisé. Masquer une erreur sans la journaliser quelque part (avecWrite-Warning, un fichier de log, ou la variable$Error) revient à transformer un problème visible en incident invisible — exactement le scénario du script de Sophie qui a laissé passer 12 serveurs sans que personne ne s’en aperçoive.
ErrorVariable : capturer l’erreur sans bloquer le script
Une alternative à try/catch, utile quand on veut simplement savoir qu’une erreur a eu lieu sans interrompre le flux du script :
Get-Service -Name "ServiceInexistant" -ErrorAction SilentlyContinue -ErrorVariable erreurService
if ($erreurService) {
Write-Warning "Le service n'a pas pu être trouvé : $($erreurService.Exception.Message)"
}$Error : l’historique de toutes les erreurs de la session
PowerShell conserve automatiquement un historique de toutes les erreurs survenues dans la session en cours, accessible via la variable automatique $Error :
$Error[0] # La dernière erreur survenue
$Error.Clear() # Vide l'historique (utile en début de script pour repartir propre)Un exemple concret Nordika : le script qui n’échoue plus en silence
En reprenant l’exemple du script de supervision multi-serveurs évoqué en introduction, voici une version qui ne perd plus aucun serveur en cours de route :
$serveurs = "SRV-01", "SRV-02", "SRV-03-HORS-SERVICE"
$resultats = @()
foreach ($serveur in $serveurs) {
try {
$service = Get-Service -Name "Spooler" -ComputerName $serveur -ErrorAction Stop
$resultats += [PSCustomObject]@{
Serveur = $serveur
Statut = $service.Status
Erreur = $null
}
} catch {
Write-Warning "$serveur injoignable : $($_.Exception.Message)"
$resultats += [PSCustomObject]@{
Serveur = $serveur
Statut = "Inconnu"
Erreur = $_.Exception.Message
}
}
}
$resultats | Format-Table -AutoSizeIci, même si SRV-03-HORS-SERVICE échoue, la boucle continue pour les serveurs suivants, et le rapport final (Format-Table, vu en 2.5) garde une trace explicite de l’échec plutôt que de l’ignorer silencieusement.
Source officielle : la documentation Microsoft
about_Try_Catch_Finallyetabout_CommonParameters(pour le détail complet des valeurs d’-ErrorAction) sont accessibles viaGet-Help about_Try_Catch_Finally, comme pour les autres rubriquesabout_déjà citées dans cette formation.
Retenez la règle la plus importante de cette leçon : un script qui échoue visiblement est un script qu’on peut corriger. Un script qui échoue en silence — par un
SilentlyContinuemal placé ou untry/catchqui ne capture jamais rien faute de-ErrorAction Stop— est un script qui vous trahira au pire moment, généralement en dehors des heures de bureau.
Dans la prochaine leçon, un TP pour mettre en pratique toute la section 5 : un script de création d’utilisateurs en masse à partir d’un fichier CSV.