À présent que vous savez comment développer un script avec des actions automatiques, des boucles et des conditions, il vous reste à comprendre comment vous pourriez gérer les différentes erreurs d’exécution qui pourraient subvenir à l'utilisation de vos cmdlets.
Découvrez l'intérêt de la gestion d’erreur
Comme vous les aimez bien, je vais vous proposer de commencer ce chapitre par une petite mise en situation.
Vous avez un script à développer, qui doit créer des dossiers, avec par exemple une CSV en source.
Genre… l'exercice final du chapitre précédent ?
Exactement ! C’est d’ailleurs sur cet exercice que nous allons baser notre exemple.
Vous l’avez vu, dans l’exercice, je dois créer un dossier.
Question : Comment je fais pour gérer le fait qu’il va provoquer une erreur si mon dossier existe déjà ?
Avec une condition qui va tester si le dossier existe déjà ?
Oui, c’est exactement ce que je proposais dans l’exercice précédent.
Maintenant, autre question, et c’est important : comment je fais pour gérer si la création du dossier ne fonctionne pas parce que je n’ai pas les droits, par exemple ?
Il faudrait modifier le test, et vérifier aussi avant si on a les droits d’écriture dans le répertoire.
D’accord. Pourquoi pas.
Mais du coup, comment gérer en plus si la création ne se fait pas parce que j’ai une erreur physique sur mon disque dur ?
On s’assure que le disque est en état d’être écrit avant ? Mais ça, je ne sais pas comment je vais le tester…
D’accord, mais bon, je pourrais ajouter encore et encore des contrôles à effectuer pour vous faire trouver des conditions. Mais comme vous l’avez dit, arrivé un moment, il faudra savoir comment tester.
Et là, je ne parle que des tests, mais il faudrait aussi mettre à chaque fois des messages d’erreurs différents, bref, beaucoup de lignes de code.
Par chance, PowerShell, par son héritage venant du framework .NET, comprend des systèmes de gestion des erreurs qui vont vous permettre de prendre en compte tous les cas de figure. Et une fois que vous y aurez goûté, vous ne pourrez plus vous en passer !
Comprenez le fonctionnement d’un bloc try…catch
Et si nous reprenions notre exemple précédent ? Dans l’idéal, plutôt que de mettre x tests différents, il faudrait pouvoir dire quelque chose comme :
“Essaie de créer mon dossier, si tu y arrives, c'est bien, sinon dis-moi pourquoi.”
Et pour ça, il y a en PowerShell, comme dans beaucoup d’autres langages de développement, des blocs prévus à cet effet : les blocs try{}, catch{} et finally{}.
Ces blocs peuvent être traduits comme ceci :
“Essaie de faire ce qu’il y a dans le bloc try{}, et si ça ne fonctionne pas, attrape l’erreur et fais ce qu’il y a dans le bloc catch{}.”
Le finally{} serait l’équivalent du :
“Et finalement, quoi qu’il arrive, tu fais ça”
Testez le bloc suivant et analysons ensuite la syntaxe de nos blocs try{} et catch{}.
try {
Get-QuelqueChose
}
catch {
Write-Host "Une erreur est apparue : $_"
}
Si tout se passe comme prévu, vous devriez avoir un message vous disant qu’une erreur est apparue, suivi de l’erreur en question.
Vous pouvez tester : si vous ne mettez que le Get-QuelqueChose
, vous aurez le droit à une belle erreur rouge.
À partir de maintenant, essayez le plus possible de mettre vos cmdlets dans des blocs try{}...catch{}. Le bloc finally{} est par expérience moins utilisé.
Avez-vous vu que dans mon bloc catch{}, j’utilise la variable spéciale des pipelines, “$_” ?
En fait, en faisant ceci, je fais appel à une autre variable spéciale dont nous n’avons pas encore parlé jusqu’à présent : $Error
. Cette variable spéciale n’a qu’une fonction : stocker les erreurs. En utilisant $_
, je fais en fait appel à cette variable $Error
, mais je lui demande uniquement de me donner le résumé de l’erreur, et non pas l’erreur complète.
Testez avec l’affichage de $Error
à la place de $_
, vous allez voir qu’il y a quelques détails en plus.
Je vous l’ai dit un peu avant, le bloc catch{} ne sera exécuté que si une erreur est considérée comme bloquante.
De même que pour des raisons bien précises, vous voudriez pouvoir ignorer totalement une erreur non bloquante. Là encore, PowerShell est bien fait.
Un paramètre existe pour pouvoir contrôler et “forcer” l’erreur à être bloquante ou pas, et va définir la façon dont PowerShell devra la gérer.
Ce paramètre est -ErrorAction
.
ErrorAction possède plusieurs valeurs :
Continue : Produit un message d’erreur et continue l’exécution.
Ignore : Ne va pas produire de message d’erreur, va continuer l’exécution. Pas d’erreur ajoutée à la variable $Error.
Inquire : Produit un message d’erreur et demande à l’utilisateur une confirmation pour arrêter ou continuer l’exécution.
SilentlyContinue : Ne va pas produire de message d’erreur, va continuer l’exécution. Les erreurs sont ajoutées à la variable $Error.
Stop : Cette option force la génération d’une erreur et stoppe l’exécution du bloc try{}.
Si vous voulez utiliser la même valeur d’ErrorAction partout dans le script, vous pouvez définir la variable $ErrorActionPreference
en début de script. Par exemple : $ErrorActionPreference “Stop”
forcera à considérer chaque erreur comme étant bloquante.
Analysez un script
Voici un script qui essaie de respecter les bonnes pratiques de développement, des différentes boucles, et une gestion d’erreur.
Analysez-le, et essayez de retrouver tous les éléments que vous avez pu voir au cours des chapitres précédents.
<#
Description : Script de jeu "trouver le nombre secret"
Usage : TrouveLeNombre
Auteur : Stiven G.
Version : 0.1
Révisions :
-0.1 (27/06/2022) : Version Initiale
#>
# Fonction d'ajout de texte dans un fichier de log
Function Add-ToLogFile($texteAAjouter) {
$dateAction = Get-Date -Format "yyyyMMdd HH:mm:ss"
Add-Content -Value $dateAction" -- "$texteAAjouter -Path "gameLog.txt"
}
#initialisation des variables
[Int]$nbrADeviner = Get-Random -Maximum 100 #Génère un nombre aléatoire entre 0 et 100
$nbrEssais = 0
#Boucle principale de jeu
While ($True) {
[Int]$nbrEntre = Read-Host "Entrez un nombre" #On force un nombre entier
$nbrEssais = $nbrEssais + 1
#Test de la valeur du nombre entré
If ($nbrEntre -lt $nbrADeviner) {
Write-Host "Le nombre à trouver est plus grand"
}
ElseIf ($nbrEntre -gt $nbrADeviner) {
Write-Host "Le nombre à trouver est plus petit"
}
Else {
Write-Host "Bravo ! Vous avez trouvé le nombre en $nbrEssais essais"
Try{
Add-ToLogFile("Gagné en $nbrEssais coups")
}
Catch {
Write-Host "Impossible d'écrire dans le fichier de log"
}
Break
}
}
À vous de jouer !
Reprenez le script que vous avez analysé dans l’exercice précédent pour lui ajouter une gestion des erreurs et une fonction qui permet d’écrire dans un fichier de log.
Un indice : Écrire dans un fichier avec la cmdlet Add-Content
.
*
*
*
*
*
*
Exemple de correction
<#
Description : Script permettant de créer en masse des dossiers utilisateurs
Usage : createDir.ps1 -csvPath <chemin vers le fichier csv>
Auteur : Stiven G.
Version : 0.3
Révisions :
-0.2 (16/08/2022): Ajout de la fonction Add-ToLogFile(String texteAAjouter)
Ajout des blocsblock try{}/catch{}
-0.1 (27/06/2022) : Version Initiale
#>
function Add-ToLogFile($texteAAjouter) {
$dateAction = Get-Date -Format "yyyyMMdd HH:mm:ss"
Add-Content -Value $dateAction" -- "$texteAAjouter -Path "log.txt"
}
$destination = "c:\users\stiven\"
$UserList = Import-Csv -Path "C:\Users\stiven\Documents\users_to_create.csv"
#boucle sur les lignes du CSV
foreach($ligne in $UserList) {
$dirName = ($ligne.prenom.Substring(0,1)+"."+$ligne.nom).toLower()
try{
#Tentative de création du dossier
New-Item $destination$dirName `
-ItemType Directory `
-ErrorAction Stop
Add-ToLogFile("Le dossier de l'utilisateur $dirName a été créé")
}
Catch {
Add-ToLogFile("ERREUR à la création du dossier : "+$_.exception.message)
}
}
En résumé
Utilisez le plus possible des blocs try{}...catch{} pour gérer les différents risques d’erreurs.
Le bloc finally{} est utilisé pour jouer des instructions dans tous les cas de figure.
Vous pouvez décider de forcer le comportement d’une erreur avec le paramètre -ErrorAction suivi de la valeur correspondant à votre choix.
Les erreurs sont stockées dans une variable spéciale appelée $Error.
Cette partie est désormais terminée. Vous avez à présent acquis des bases solides en développement de scripts PowerShell. Dans la dernière partie, vous allez pouvoir les appliquer dans un contexte plus proche du métier de technicien informatique. Mais avant cela, prenez le temps de répondre au quiz pour valider vos connaissances !