Sophie relit le script de supervision écrit en 5.3 : « Ce script fonctionne pour Spooler, W32Time et Dnscache. Mais si je te demande la même vérification sur un autre service la semaine prochaine, tu vas recopier tout le bloc ? » C’est exactement le problème que résolvent les fonctions : transformer un bloc de code qu’on recopie sans cesse en un poste de travail réutilisable, qu’on appelle à volonté.
Créer une première fonction
Une fonction se déclare avec le mot-clé function, suivi d’un nom respectant la convention Verbe-Nom vue en 2.1 :
function Test-ServiceCritique {
param (
[string]$NomService
)
$service = Get-Service -Name $NomService -ErrorAction SilentlyContinue
if ($service.Status -eq "Running") {
Write-Output "$NomService : OK"
} else {
Write-Warning "$NomService est arrêté, redémarrage..."
Start-Service -Name $NomService
}
}Une fois définie (par exemple en tête de script, ou dans un module comme on le verra en section 6), on l’appelle simplement par son nom :
Test-ServiceCritique -NomService "Spooler"
Test-ServiceCritique -NomService "W32Time"
Test-ServiceCritique -NomService "Dnscache"Le bloc param ( ) remplace la recopie manuelle vue en 5.3 : la logique n’existe qu’à un seul endroit, appelée trois fois avec un paramètre différent.
Plusieurs paramètres, valeurs par défaut
Une fonction peut accepter plusieurs paramètres, et certains peuvent avoir une valeur par défaut, utilisée si l’appelant ne la précise pas :
function Test-ServiceCritique {
param (
[string]$NomService,
[string]$ComputerName = $env:COMPUTERNAME
)
$service = Get-Service -Name $NomService -ComputerName $ComputerName -ErrorAction SilentlyContinue
Write-Output "$NomService sur $ComputerName : $($service.Status)"
}Test-ServiceCritique -NomService "Spooler" # Utilise la machine locale
Test-ServiceCritique -NomService "Spooler" -ComputerName "SRV-02" # Cible un serveur distantTyper ses paramètres : une habitude qui évite bien des erreurs
Préciser le type entre crochets ([string], [int], [bool]…) n’est pas obligatoire, mais fortement recommandé dès qu’un script dépasse quelques lignes :
function New-CompteNordika {
param (
[string]$Nom,
[int]$AgeCompte,
[bool]$EstCritique
)
# ...
}Sans typage, $AgeCompte accepterait n’importe quelle valeur, y compris du texte, et l’erreur ne se révélerait que plus loin dans le script, au moment d’un calcul — souvent avec un message confus, difficile à relier à sa cause réelle. Avec le type précisé, PowerShell refuse l’appel immédiatement si la valeur ne correspond pas, avec un message d’erreur clair et localisé.
Retour d’expérience terrain : sur les incidents de production que j’ai eu à diagnostiquer, une bonne partie provenait d’un paramètre mal typé, dont l’erreur ne remontait que plusieurs lignes plus loin dans le script — rendant le diagnostic bien plus long que nécessaire. Typer systématiquement ses paramètres, même dans un script « rapide », fait gagner un temps précieux le jour où ça déraille.
Rendre un paramètre obligatoire
Mandatory force l’appelant à fournir une valeur, sous peine d’un message d’erreur explicite (ou d’une invite automatique demandant la valeur manquante) :
function New-CompteNordika {
param (
[Parameter(Mandatory = $true)]
[string]$Nom
)
# ...
}Renvoyer une valeur avec return
Une fonction peut aussi calculer une valeur et la renvoyer à l’appelant, comme vu implicitement avec Write-Output en leçon 3.4 :
function Get-EspaceDisqueLibre {
param (
[string]$Lettre = "C"
)
$disque = Get-Volume -DriveLetter $Lettre
return [math]::Round($disque.SizeRemaining / 1GB, 1)
}
$espaceLibre = Get-EspaceDisqueLibre
Write-Output "Espace libre : $espaceLibre Go"return arrête immédiatement l’exécution de la fonction et renvoie la valeur indiquée — à ne pas confondre avec Write-Output, qui alimente le pipeline sans forcément arrêter le reste de la fonction.
Un exemple concret Nordika : la fonction au cœur du script d’inventaire
En reprenant le TP de la section 4, la vérification des services critiques devient une fonction réutilisable, appelable pour n’importe quel serveur :
function Get-EtatServicesCritiques {
param (
[string[]]$Services,
[string]$ComputerName = $env:COMPUTERNAME
)
foreach ($nomService in $Services) {
$service = Get-Service -Name $nomService -ComputerName $ComputerName -ErrorAction SilentlyContinue
[PSCustomObject]@{
Service = $nomService
Serveur = $ComputerName
Statut = $service.Status
}
}
}
Get-EtatServicesCritiques -Services "Spooler", "W32Time", "Dnscache" -ComputerName "SRV-02"[string[]] (avec les crochets) indique un tableau de chaînes, vu en section 3 — la fonction accepte donc plusieurs noms de services en un seul appel. [PSCustomObject]@{ } mérite un mot d’explication : cette syntaxe transforme une hashtable (vue en 3.3) en un véritable objet PowerShell, avec des propriétés nommées, exploitable ensuite par tout le trio Sort-Object/Where-Object/Format-Table vu en section 2 — bien plus utile que du simple texte affiché.
Source officielle : la documentation Microsoft
about_Functions_Advanced_Parametersdétaille l’ensemble des attributs disponibles pour un paramètre (Mandatory,ValueFromPipeline,ValidateSet…), accessible viaGet-Help about_Functions_Advanced_Parameters.
Une fonction bien conçue, c’est un poste de travail permanent installé une bonne fois pour toutes dans l’atelier Nordika : n’importe quel script futur pourra l’appeler sans jamais avoir à recopier sa logique interne.
Dans la prochaine leçon, on termine cette section scripting avec un sujet essentiel : la gestion des erreurs, try/catch et ErrorAction.