Best Practices : Analysez votre code PowerShell avec PSScriptAnalyzer

I. Présentation

PSScriptAnalyzer est un module PowerShell qui vérifie le code de vos scripts et de vos modules pour évaluer la qualité de votre code en se basant sur un ensemble de règles de bonnes pratiques.

Vous pouvez utiliser les règles prédéfinies et correspondantes aux best practices identifiées par l'équipe PowerShell et la communauté autour de ce langage. De plus, vous pourrez créer votre propre set de règles propre à votre entreprise.

L'avantage d'utiliser PSScriptAnalyzer c'est qu'il vous indiquera les résultats de son diagnostic selon des règles d'avertissements ou d'erreurs, avec le risque potentiel, mais aussi une suggestion pour corriger les points mis en évidence. Grâce à cela, vous allez pouvoir d'une part améliorer la qualité de votre code, mais aussi vous améliorer de manière générale pour que vous appliquiez ces best practices naturellement.

Dans ce tutoriel, on installera le module et on le mettra en pratique sur quelques scripts.

Version vidéo du tutoriel :

II. Installer PSScriptAnalyzer

Pour commencer, nous allons installer ce module. Il est compatible avec Windows à partir de PowerShell 3.0, et à en croire la page du module, il fonctionne avec PowerShell Core sous Linux, du moins sur Ubuntu 14.04. La page du module : GitHub PSScriptAnalyzer

Pour l'installer, c'est tout simple, directement depuis la PSGallery :

Install-Module -Name PSScriptAnalyzer -Repository PSGallery -Force

La preuve ci-dessous en image 🙂

Avant de continuer, on peut lister les commandlets du module, qui sont au nombre de 2 pour le moment.

Pour utiliser le module PSScriptAnalyzer dans plusieurs cas concrets, notamment le commandlet "Invoke-ScriptAnalyzer" qui permet de démarrer une analyse du code sur un script ou module PowerShell, j'ai utilisé quelques scripts que j'ai publiés sur mon GitHub (et codé par mes soins).

III. PSScriptAnalyzer : Exemple n°1

Commençons par le script "Backup-AllGPO.ps1" qui permet de sauvegarder ses GPO... Pour lancer l'analyse sur ce script, il faut invoquer la commande suivante :

Invoke-ScriptAnalyzer -Path .\AD-Backup-AllGPO\

Vous remarquerez que l'on ne précise pas un fichier PS1 directement, mais un dossier, ce qui implique que tous les fichiers PowerShell seront analysés. Le résultat de l'analyse contient une propriété "ScriptName" qui indiquera le nom du script précisément.

Sur la copie d'écran ci-dessous, vous remarquerez qu'une petite dizaine de corrections sont suggérées par le ScriptAnalyzer. Bien qu'il y en ait plusieurs identiques et qu'elles ne soient pas critiques dans le sens où ça n'empêche pas le script de fonctionner, il est important d'y prêter attention.

Faisons le point.

  • Information : PSAvoidUsingPositionalParameters

Cette règle indique qu'il vaut mieux éviter d'utiliser des paramètres positionnels, mais qu'il faut plutôt nommer les paramètres et indiquer une valeur pour chaque paramètre. En fait, dans mon script j'utilise "Write-Host" suivi du texte à afficher dans la console sans spécifier de paramètre, la bonne pratique voudrez, qu'au lieu d'écrire :

Write-Host "Mon texte"

On écrit :

Write-Host -Object "Mon texte"

Ce qui me permettra de corriger deux points remontés par le ScriptAnalyzer.

Note : Dans le résultat affiché dans la console, la propriété "Line" affiche la ligne concernée par "l'erreur" remontée par l'analyseur au sein du script nommé avec la propriété ScriptName.

 

  • Warning : PSAvoidUsingWriteHost

Cette règle indique que le commandlet "Write-Host" est utilisé alors qu'il ne pourra pas fonctionner dans tous les cas de figure, mais surtout qu'il vaut mieux utiliser Write-Output, Write-Verbose ou Write-Information à la place. Pour plus d'informations sur cette recommandation : Write-Host, Attention !

Ce qui n'est pas idiot, car l'avantage des autres commandlets c'est qu'on peut rediriger la sortie, voire même la transmettre à un autre objet, ce n'est pas simplement de l'affichage dans la console. Une autre manière de gérer la sortie de texte, mais pour suivre les bonnes pratiques, il convient d'adapter le script.

Pour ma part, je m'oriente vers Write-Output puisque son comportement se rapproche fortement de Write-Host pour afficher du contenu dans la console. Après, libre à vous de choisir selon vos besoins la formule la mieux adaptée.

  • Warning : PSAvoidUsingCmdletAliases

Un avertissement qui revient deux fois, à propos de "Select" et de "Foreach" qui sont des alias des commandes "Select-Object" et "Foreach-Object". Le Script Analyzer recommande d'utiliser les noms complets des commandlets plutôt que les alias.

Ce qui implique de remplacer les occurrences de "Select" par "Select-Object" et celles de "Foreach" par "Foreach-Object".

Après avoir suivi les conseils et recommandations de PSScriptAnalyzer, on peut voir qu'il n'y a plus de modifications à apporter au script :

IV. PSScriptAnalyzer : Exemple n°2

Prenons l'exemple désormais du script "Start-BitsDownloadRecursive.ps1" qui permet de télécharger une arborescence complète de fichiers par l'intermédiaire de BITS. Si l'on regarde la sortie de la commande Invoke-ScriptAnalyzer, on remarque les recommandations déjà obtenues dans l'exemple précédent, on sait donc comment les corriger. 🙂

Finalement, ce n'est pas étonnant de voir les mêmes règles matcher puisque si l'on a la même logique dans ses scripts, on commet les mêmes imperfections. L'objectif étant de s'améliorer.

V. PSScriptAnalyzer : Exemple n°3

Pour finir, on va prendre comme exemple le script "Add-NetworkPrinter.ps1" qui permet d'ajouter une imprimante réseau sur une machine via PowerShell évidemment. Le Script Analyzer pour ce script ne ressort pas les mêmes règles qu'auparavant.

  • Warning : PSAvoidUsingWMICmdlet

Pour travailler avec les imprimantes, j'utilise le commandlet "Get-WmiObject" qui comme son nom l'indique effectue une requête WMI sur la machine. Cependant, il est désormais préférable d'effectuer une requête CIM pour bénéficier du modèle commun à différents systèmes d'exploitation.

Pour ma part, j'estime que pour le moment pour des raisons de compatibilité et dans le cas présent, qu'il est préférable de rester en WMI puisque ça n'apportera pas grand-chose de passer sur une requête CIM. Ceci notamment, car il faut au minimum PowerShell 3.0 pour supporter les requêtes CIM.

Dans le cas de mon script, voici une commande pour lister les imprimantes, que ce soit en CIM ou en WMI on obtient les mêmes informations, seul le format de la sortie est différent.

Ce tutoriel sur le module PSScriptAnalyzer touche à sa fin, j'espère que ça vous encourage à l'utiliser pour vos créations afin d'avoir un code optimisé et répondant aux bonnes pratiques. Ce travail de fond facilite également la reprise du code par une autre personne puisque c'est bénéfique pour la compréhension du code également.

Pour aller plus loin :

  • Vous pouvez lister les règles existantes et ainsi en prendre connaissance avant même qu'elles ressortent lors d'une analyse : Get-ScriptAnalyzerRule
  • Vous pouvez inclure ou exclure des règles en utilisant les paramètres "IncludeRule" et "ExcludeRule" suivi du nom ou des noms de règles

 

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Florian Burnel

Co-Fondateur d'IT-Connect, je souhaite partager mes connaissances et expériences avec vous, et comme la veille techno' est importante je partage aussi des actus.

florian a publié 1563 articles sur IT-Connect.See all posts by florian

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *