Réutiliser son code avec les modules
Objectifs de la séance
- Comprendre à quoi sert un module PowerShell
- Écrire un module de script
.psm1et en exporter les fonctions publiques - Documenter une fonction pour qu'elle réponde à
Get-Help - Installer un module tiers depuis la PowerShell Gallery
Notions théoriques
Pourquoi un module
Une fonction utile ne devrait pas être recopiée dans dix scripts différents : c'est exactement le problème que résolvaient déjà les fonctions au niveau 1, et que résout include/require en PHP, ou source en Bash. Un module PowerShell va plus loin : il regroupe plusieurs fonctions dans un fichier réutilisable, chargeable depuis n'importe quel script par une seule instruction.
Vocabulaire
- une cmdlet est une commande native de PowerShell, écrite en .NET ;
- une fonction est une commande que vous écrivez vous-même, en PowerShell ;
- un module est un ensemble de fonctions (et éventuellement de cmdlets) regroupées dans un fichier ou un dossier réutilisable.
Trois types de fichiers de module existent : le module de script (.psm1, celui que nous écrirons aujourd'hui), le manifeste (.psd1, des métadonnées sur le module), et le module binaire (écrit en C#, hors programme).
Découvrir les modules disponibles
Get-Module
Get-Module -ListAvailable
Get-Command -Module ActiveDirectory
Get-Help Get-Service -Examples
Get-Module liste les modules déjà chargés dans la session courante ; Get-Module -ListAvailable liste tous ceux installés sur la machine, chargés ou non.
Charger un module
Import-Module AdminParc
Remove-Module AdminParc
Depuis PowerShell 3, un module correctement installé se charge même automatiquement dès qu'une de ses commandes est utilisée — Import-Module explicite reste utile pendant le développement, notamment avec -Force pour recharger une version modifiée.
Où placer un module : $env:PSModulePath
PowerShell recherche les modules dans plusieurs emplacements listés dans la variable $env:PSModulePath, notamment le dossier personnel Documents\PowerShell\Modules (pas besoin de droits administrateur).
Règle stricte à respecter : le dossier contenant le module doit porter exactement le même nom que le fichier .psm1 qu'il contient. Documents\PowerShell\Modules\AdminParc\AdminParc.psm1 fonctionne ; Documents\PowerShell\Modules\Outils\AdminParc.psm1 ne sera jamais trouvé par Import-Module AdminParc.
Écrire un module
Un module de script est un fichier .psm1 classique, contenant une ou plusieurs fonctions déclarées avec function Verbe-Nom { ... }, exactement comme au niveau 1. La seule différence est l'instruction finale :
Export-ModuleMember -Function Get-InventairePoste, Write-Journal
Elle définit quelles fonctions sont publiques (visibles depuis l'extérieur du module) : une fonction utilitaire interne, non listée ici, reste privée au module.
Les verbes approuvés
PowerShell impose une convention de nommage stricte : Verbe-Nom, où le verbe fait partie d'une liste approuvée, consultable avec Get-Verb. Utiliser un verbe hors de cette liste (par exemple Creer-Utilisateur au lieu de New-Utilisateur) déclenche un avertissement à l'import du module.
Documenter une fonction
Un bloc de commentaire spécial, placé juste au-dessus de la fonction, la rend interrogeable par Get-Help :
function Write-Journal {
<#
.SYNOPSIS
Ecrit un message horodate dans le journal du parc.
.DESCRIPTION
Ajoute une ligne datee au fichier de journal indique.
.PARAMETER Message
Le texte a journaliser.
.EXAMPLE
Write-Journal "Sauvegarde terminee" -Niveau "INFO"
#>
param(...)
}
Documenter ainsi ses fonctions les rend accessibles avec Get-Help Write-Journal -Examples, exactement comme pour une cmdlet native — bien plus durable qu'un commentaire libre, qui a tendance à ne plus être lu ni mis à jour.
Le manifeste
Un manifeste .psd1 ajoute des métadonnées à un module (numéro de version, auteur, dépendances) :
New-ModuleManifest -Path AdminParc.psd1 -RootModule AdminParc.psm1 -ModuleVersion 1.0.0 -Author "Votre nom"
Il n'est pas indispensable pour un module d'usage personnel, mais devient nécessaire dès qu'un module est partagé ou versionné sérieusement.
La PowerShell Gallery
Des milliers de modules tiers sont disponibles en ligne :
Find-Module -Name "PSWindowsUpdate"
Install-Module -Name "PSWindowsUpdate" -Scope CurrentUser
Update-Module -Name "PSWindowsUpdate"
Installer un module tiers revient à exécuter du code écrit par quelqu'un d'autre sur votre machine. Vérifiez la réputation de l'auteur et le nombre de téléchargements avant d'installer un module en dehors d'un contexte d'apprentissage, et préférez -Scope CurrentUser à une installation système.
Exemple pratique
# Fichier : Documents\PowerShell\Modules\AdminParc\AdminParc.psm1
function Write-Journal {
<#
.SYNOPSIS
Ecrit un message horodate dans le journal du parc.
.EXAMPLE
Write-Journal "Sauvegarde terminee" -Niveau "INFO"
#>
param(
[Parameter(Mandatory = $true)][string]$Message,
[string]$Niveau = "INFO",
[string]$Fichier = "$env:TEMP\adminparc.log"
)
$ligne = "[{0}] {1} : {2}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Niveau, $Message
Add-Content -Path $Fichier -Value $ligne
}
function Get-EspaceDisque {
param([string]$Machine = $env:COMPUTERNAME)
Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName $Machine -Filter "DriveType=3" |
ForEach-Object {
[PSCustomObject]@{
Machine = $Machine
Lecteur = $_.DeviceID
LibreGo = [math]::Round($_.FreeSpace / 1GB, 1)
TotalGo = [math]::Round($_.Size / 1GB, 1)
}
}
}
Export-ModuleMember -Function Write-Journal, Get-EspaceDisque
Puis, dans une console :
Import-Module AdminParc -Force
Get-Command -Module AdminParc
Get-Help Get-EspaceDisque -Examples
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Ce TP s'exécute entièrement sur n'importe quel poste Windows, sans droits administrateur : le dossier Documents\PowerShell\Modules appartient à l'utilisateur courant. Seule précaution : vérifiez au préalable que Get-ExecutionPolicy -Scope CurrentUser renvoie RemoteSigned (rappel du niveau 1), sans quoi le .psm1 sera bloqué comme n'importe quel script.
Étape 1 — Déclarer un paramètre obligatoire
Déclarer un paramètre Mandatory évite d'écrire un if de vérification en début de fonction : PowerShell refuse l'appel tant que le paramètre n'est pas fourni.
Étape 2 — N'exporter que les fonctions publiques
N'exportez que les fonctions destinées à être utilisées depuis l'extérieur du module : une fonction utilitaire interne reste privée, comme une méthode private en programmation orientée objet.
Étape 3 — Documenter la fonction
Contrairement à un commentaire libre, un bloc .SYNOPSIS/.EXAMPLE est lu par Get-Help : il reste accessible et cohérent tant qu'il accompagne la fonction.
Étape 4 — Importer et vérifier le module
Utilisez Import-Module AdminParc -Force tant que vous modifiez le fichier .psm1 : sans -Force, une version déjà chargée en mémoire n'est pas remplacée par vos derniers changements.