Fonctions et gestion des erreurs
Un bon script PowerShell est réutilisable et robuste. Les fonctions encapsulent la logique, la gestion des erreurs empêche les crashs silencieux.
Définir une fonction
function Get-DiskReport {
param(
[Parameter(Mandatory)]
[string]$ComputerName,
[int]$SeuilAlerte = 20 # valeur par défaut
)
$disques = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $ComputerName -Filter "DriveType=3"
foreach ($disque in $disques) {
$librePct = [math]::Round(($disque.FreeSpace / $disque.Size) * 100, 1)
[PSCustomObject]@{
Serveur = $ComputerName
Lettre = $disque.DeviceID
Total_GB = [math]::Round($disque.Size / 1GB, 1)
Libre_GB = [math]::Round($disque.FreeSpace / 1GB, 1)
Libre_Pct = $librePct
Alerte = $librePct -lt $SeuilAlerte
}
}
}
# Utilisation
Get-DiskReport -ComputerName "SRV-FILE01"
Get-DiskReport -ComputerName "SRV-WEB01" -SeuilAlerte 10
Gestion des erreurs avec try/catch
function Test-ServiceCritique {
param([string]$Nom, [string]$Serveur = $env:COMPUTERNAME)
try {
$service = Get-Service -Name $Nom -ComputerName $Serveur -ErrorAction Stop
if ($service.Status -ne 'Running') {
Write-Warning "$Nom est arrêté sur $Serveur : tentative de démarrage..."
Start-Service -InputObject $service -ErrorAction Stop
Write-Host "$Nom démarré avec succès." -ForegroundColor Green
} else {
Write-Host "$Nom est actif sur $Serveur." -ForegroundColor Green
}
} catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
Write-Error "Service $Nom introuvable sur $Serveur : $_"
} catch {
Write-Error "Erreur inattendue sur $Serveur/$Nom : $_"
}
}
Paramètres avancés
function Send-AlertEmail {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[string]$Message,
[ValidateSet('Info', 'Warning', 'Critical')]
[string]$Niveau = 'Info'
)
process {
if ($PSCmdlet.ShouldProcess("Envoi email : $Message")) {
Write-Host "[$Niveau] $Message"
# Logique d'envoi réel ici
}
}
}
# -WhatIf fonctionne automatiquement grâce à SupportsShouldProcess
"Disque plein" | Send-AlertEmail -Niveau Critical -WhatIf
Cas concret : script de surveillance complet
$serveurs = @("SRV-DC01", "SRV-FILE01", "SRV-WEB01")
$erreurs = @()
foreach ($srv in $serveurs) {
try {
$rapport = Get-DiskReport -ComputerName $srv -ErrorAction Stop
$alertes = $rapport | Where-Object { $_.Alerte -eq $true }
if ($alertes) {
$erreurs += $alertes
Write-Warning "Espace faible sur $srv"
}
} catch {
Write-Error "Impossible de joindre $srv : $_"
$erreurs += [PSCustomObject]@{ Serveur = $srv; Lettre = 'N/A'; Alerte = $true }
}
}
if ($erreurs.Count -gt 0) {
$erreurs | Export-Csv -Path C:\Alertes\disques-$(Get-Date -Format 'yyyyMMdd').csv -NoTypeInformation
Write-Host "$($erreurs.Count) alerte(s) exportée(s)." -ForegroundColor Red
}
Erreurs fréquentes
-ErrorAction Stopoublié dans try/catch : sans ce paramètre, les erreurs non-terminantes (cmdlets standard) ne sont pas capturées par catch.- catch trop large : un seul
catch { }cache tous les types d'erreur. Préférez des blocscatch [TypeException]spécifiques d'abord. - Fonctions sans
param(): sans blocparam, pas de validation automatique, pas deMandatory, pas de pipeline.
À retenir
function Nom { param([Parameter(Mandatory)][string]$P) ... }→ structure de base.try { } catch { }+-ErrorAction Stop→ capturer les erreurs cmdlet.[CmdletBinding(SupportsShouldProcess)]→ activer-WhatIfautomatiquement.- Tester toujours avec
-WhatIfavant d'exécuter un script destructif en production.