Le fonctionnement des erreurs avec PowerShell
Sommaire
I. Présentation
Quand vous allez écrire vos scripts PowerShell, vous serez obligatoirement confrontés à des erreurs. Même un code parfaitement écrit et qui respecte les bonnes pratiques est susceptible de générer des erreurs : une valeur inattendue pour un paramètre de cmdlet, une commande mal écrite, un problème de droits sur un ordinateur, une opération non autorisée, etc... Les situations lors desquelles nous pouvons rencontrer une erreur sont nombreuses... Et, nous devons être capables d'interpréter ces erreurs, mais également de les gérer.
Dans ce premier chapitre, nous allons évoquer le fonctionnement des erreurs avec PowerShell, car ce sera essentiel pour la suite puisque dans le prochain chapitre, nous verrons comment gérer les erreurs avec "Try-Catch et Finally.
Au-delà de la variable automatique "$?" qui permet de savoir si la dernière commande s'est correctement exécutée ou non (un booléen est retourné), PowerShell met à notre disposition la variable "$Error", ainsi que le cmdlet "Get-Error".
II. Les erreurs fatales et non fatales
Dans PowerShell, il existe deux types principaux d'erreurs : les erreurs fatales et les erreurs non fatales, que nous pouvons aussi appeler les erreurs bloquantes et les erreurs non bloquantes. En anglais, deux termes sont associés : terminating error et non-terminating error.
Les erreurs fatales sont des erreurs graves qui arrêtent immédiatement l'exécution du script. Elles peuvent se produire dans différentes situations et un cmdlet ne retournera pas systématiquement une erreur fatale. Cette erreur peut se produire si un problème est rencontré et qu'il bloque la suite de l'exécution.
À l'inverse, et vous devez vous en douter, les erreurs non fatales n'arrêtent pas l'exécution du script. Elles signalent simplement qu'une erreur s'est produite, mais le script continue à s'exécuter. La gestion de ces deux types d'erreurs est essentielle dans vos scripts.
III. La variable $Error
Lorsque vous travaillez avec PowerShell, il est important de comprendre comment utiliser et interagir avec la variable "$Error". Cette variable gérée par PowerShell joue un rôle crucial puisque nous allons l'utiliser pour récupérer les dernières erreurs, ce qui sera fort utile en phase de débogage. Elle contient les erreurs fatales et non fatales.
Tout d'abord, sachez que la variable "$Error" est une variable automatique qui contient un tableau des dernières erreurs qui se sont produites lors de l'exécution d'un script ou d'une commande. L'erreur la plus récente est toujours à l'index 0 du tableau. À chaque fois qu'une erreur que l'on appelle aussi exception est générée, celle-ci est ajoutée au tableau "$Error".
Son contenu est éphémère puisqu'elle est nettoyée à la fin de chaque session PowerShell. Autrement dit, si vous fermez la console PowerShell et que vous la rouvrez, "$Error" sera vide.
En pratique, la variable "$Error" peut être utilisée pour obtenir des informations détaillées sur les erreurs. Vous pouvez afficher toutes les erreurs en saisissant tout simplement "$Error" dans la console. De plus, vous pouvez accéder à une erreur spécifique en spécifiant son numéro d'index.
Exécutez les deux commandes ci-dessous afin de générer deux erreurs :
Get-Contenu -Path "C:\temp\fichier.txt"
Get-Content -Path "C:\temp\fichier.txt"
Dans le premier cas, le nom du cmdlet est incorrect tandis que dans le second cas, le fichier est introuvable.
Nous pouvons consulter la variable "$Error" pour afficher ces deux erreurs :
$Error
Puis, si nous souhaitons uniquement récupérer l'erreur la plus récente (ou une erreur spécifique vis-à-vis de son index) :
$Error[0]
Plutôt que de récupérer tout le message d'erreur, nous pouvons faire en sorte de récupérer certaines informations précises.
- Récupérer uniquement le texte correspondant à l'erreur :
$Error[0].Exception.Message
Ici, ce sera : "Impossible de trouver le chemin d'accès « C:\temp\fichier.txt », car il n'existe pas.".
- Récupérer le numéro de ligne dans le script :
$Error[0].InvocationInfo.ScriptLineNumber
Ici, ce sera "1" car il s'agit d'une commande exécutée dans la console, et non d'un script.
- Récupérer le type d'erreur généré :
$Error[0].Exception.GetType().FullName
Ici, la valeur retournée est : "System.Management.Automation.ItemNotFoundException".
À chaque fois, selon l'information que nous souhaitons récupérer, nous allons lire une propriété différente.
IV. Le cmdlet Get-Error
Depuis PowerShell 7, nous avons la possibilité d'utiliser le cmdlet "Get-Error" pour obtenir des informations sur les dernières erreurs rencontrées dans la session actuelle. Le cmdlet "Get-Error" permet d'obtenir un objet "PSExtendedError" et elle est alimentée à partir des informations contenues dans "$Error".
Get-Error
Le résultat retourné par "Get-Error" est mis en forme, en comparaison de la lecture directe de "$Error".
Ce qui est pratique avec "Get-Error", c'est le paramètre "-Newest" car il permet d'obtenir les X plus récentes erreurs. Par exemple, pour obtenir les trois erreurs les plus récentes, nous devons simplement exécuter cette commande :
Get-Error -Newest 3
V. La variable $ErrorActionPreference
"$ErrorActionPreference" est une variable de préférence intégrée dans PowerShell qui détermine comment il doit gérer les erreurs non bloquantes. Plusieurs valeurs sont valides et par défaut la valeur est "Continue".
Les valeurs suivantes sont acceptées : SilentlyContinue, Stop, Continue, Inquire, Ignore, Suspend et Break. Il est à noter que la valeur "Break" n'est pas prise en charge par Windows PowerShell, et que les valeurs "Ignore" et "Suspend" sont prises en charge uniquement par le paramètre "-ErrorAction" que nous allons étudier par la suite.
Valeur | Description |
---|---|
SilentlyContinue | Les erreurs sont supprimées et le script continue son exécution. |
Stop | L'exécution du script est arrêtée dès qu'une erreur survient. |
Continue | Les erreurs sont affichées dans la console, mais le script continue son exécution. Valeur par défaut. |
Inquire | PowerShell demande à l'utilisateur s'il veut continuer chaque fois qu'une erreur se produit. |
Ignore | L'erreur retournée par la commande est ignorée et n'est même pas ajoutée à la variable $Error. |
Suspend | Pour les workflows PowerShell uniquement, afin de le suspendre en cas d'erreur pour permettre le débogage. |
Break | Quand une erreur se produit, PowerShell active le débogueur sur l'instruction en cours d'exécution. |
Pour définir une autre valeur, il convient d'affecter une nouvelle valeur à la variable :
$ErrorActionPreference = "stop"
La valeur de la variable "$ErrorActionPreference" peut être modifiée dans le profil PowerShell pour être persistante ou directement dans une console PowerShell pour s'appliquer uniquement le temps que la console est ouverte, ou en début de script. Néanmoins, il est plutôt recommandé d'utiliser le paramètre "-ErrorAction".
VI. Le paramètre ErrorAction
Le paramètre "-ErrorAction" est un paramètre commun que vous pouvez utiliser avec n'importe quelle cmdlet dans PowerShell, y compris avec une fonction que vous avez développée si celle-ci bénéficie du paramètre CmdletBinding().
Ce paramètre vous permet de spécifier le comportement de la commande exécutée si une erreur non bloquante se produit lors de l'exécution. Les valeurs que vous pouvez attribuer à "-ErrorAction" sont les mêmes que celles de la variable "$ErrorActionPreference", à savoir : "SilentlyContinue", Stop, Continue, Inquire, Ignore, Suspend et Break.
Par exemple, si vous utilisez "Stop" comme valeur, une erreur fatale sera générée et l'exécution du script sera stoppée (sauf si un bloc d'instruction "Try-Catch" est utilisé pour capturer l'erreur). Si vous utilisez "SilentlyContinue", le cmdlet ignorera l'erreur et le script poursuivra son exécution. Ce paramètre est très utile pour gérer les erreurs directement au niveau des cmdlets, de façon individuelle et indépendante, au sein d'un script PowerShell.
Voici comment utiliser ce paramètre :
Get-Content -Path "C:\temp\fichier.txt" -ErrorAction Stop
VII. Conclusion
Maintenant que vous en savez plus sur le fonctionnement des erreurs en PowerShell, nous allons apprendre à gérer les erreurs grâce à l'utilisation de Try, Catch et Finally.