Fonctions et scripts

Créer une fonction

Une fonction PowerShell permet de regrouper des commandes réutilisables :

# Syntaxe de base
function Say-Hello {
    Write-Output "Bonjour !"
}

# Appeler la fonction
Say-Hello

Fonctions avec paramètres

# Paramètres simples
function Say-Hello {
    param(
        [string]$Nom
    )
    Write-Output "Bonjour, $Nom !"
}

Say-Hello -Nom "Alice"
Say-Hello "Alice"         # Le paramètre positionnel fonctionne aussi

# Paramètres avec valeur par défaut
function Say-Hello {
    param(
        [string]$Nom = "monde"
    )
    Write-Output "Bonjour, $Nom !"
}

Say-Hello              # Affiche : Bonjour, monde !
Say-Hello "Alice"      # Affiche : Bonjour, Alice !

Fonctions avec retour de valeur

function Get-DiskSpaceGB {
    param([string]$Drive = "C")
    $disk = Get-PSDrive $Drive
    return [math]::Round($disk.Free / 1GB, 2)
}

$espace = Get-DiskSpaceGB
Write-Output "Espace libre : $espace Go"

Exemple pratique : kill-port

Voici une fonction très utile pour les développeurs : tuer un processus qui occupe un port (par exemple quand votre serveur de développement reste bloqué sur le port 3000).

function kill-port {
    param([int]$Port)

    $connection = Get-NetTCPConnection -LocalPort $Port -ErrorAction SilentlyContinue
    if ($connection) {
        $processId = $connection.OwningProcess | Select-Object -First 1
        $processName = (Get-Process -Id $processId).ProcessName
        Write-Output "Port $Port utilisé par $processName (PID: $processId)"
        Stop-Process -Id $processId -Force
        Write-Output "Processus arrêté."
    } else {
        Write-Output "Aucun processus trouvé sur le port $Port."
    }
}

Utilisation :

kill-port 3000
kill-port 3020
kill-port 8080

Structures de contrôle

Conditions

$age = 25

if ($age -ge 18) {
    Write-Output "Majeur"
} elseif ($age -ge 16) {
    Write-Output "Presque majeur"
} else {
    Write-Output "Mineur"
}

# Switch
$jour = "lundi"
switch ($jour) {
    "lundi"    { Write-Output "Début de semaine" }
    "vendredi" { Write-Output "Bientôt le week-end" }
    default    { Write-Output "Milieu de semaine" }
}

Boucles

# ForEach
$fruits = @("pomme", "banane", "orange")
foreach ($fruit in $fruits) {
    Write-Output "J'aime les $fruit"
}

# ForEach-Object (dans le pipeline)
Get-ChildItem *.txt | ForEach-Object {
    Write-Output "Fichier : $($_.Name) - Taille : $($_.Length) octets"
}

# For classique
for ($i = 0; $i -lt 5; $i++) {
    Write-Output "Itération $i"
}

# While
$compteur = 0
while ($compteur -lt 3) {
    Write-Output "Compteur : $compteur"
    $compteur++
}

Créer un script .ps1

Un script PowerShell est un fichier texte avec l'extension .ps1.

Mon premier script

Créez un fichier nettoyage.ps1 :

# nettoyage.ps1 - Nettoie les fichiers temporaires
param(
    [string]$Dossier = $env:TEMP,
    [int]$JoursAnciennete = 7
)

$dateLimite = (Get-Date).AddDays(-$JoursAnciennete)
$fichiers = Get-ChildItem -Path $Dossier -Recurse -File |
    Where-Object { $_.LastWriteTime -lt $dateLimite }

Write-Output "Fichiers de plus de $JoursAnciennete jours dans $Dossier : $($fichiers.Count)"

foreach ($fichier in $fichiers) {
    Write-Output "  Suppression : $($fichier.Name)"
    Remove-Item $fichier.FullName -Force -ErrorAction SilentlyContinue
}

Write-Output "Nettoyage terminé."

Exécuter un script

# Exécuter le script
.\nettoyage.ps1

# Avec des paramètres
.\nettoyage.ps1 -Dossier "C:\logs" -JoursAnciennete 30

Politique d'exécution

Par défaut, Windows bloque l'exécution des scripts PowerShell. Pour les autoriser :

# Vérifier la politique actuelle
Get-ExecutionPolicy

# Autoriser les scripts locaux (recommandé)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

# Les valeurs possibles :
# Restricted    - Aucun script (par défaut)
# RemoteSigned  - Scripts locaux OK, téléchargés doivent être signés
# Unrestricted  - Tout est autorisé (déconseillé)

Try/Catch : gestion des erreurs

try {
    $contenu = Get-Content "fichier-inexistant.txt" -ErrorAction Stop
    Write-Output $contenu
} catch {
    Write-Output "Erreur : $($_.Exception.Message)"
} finally {
    Write-Output "Bloc finally exécuté dans tous les cas"
}