Introduction
Les fonctions en PowerShell sont des outils puissants pour automatiser et simplifier les tâches répétitives. Dans cet article, nous allons explorer en profondeur les différentes façons de créer et d’utiliser des fonctions en PowerShell, en utilisant des exemples concrets liés à la gestion d’une bibliothèque numérique.
Création de fonctions de base
Fonction simple
function Calculer-DureePret($dateEmprunt, $dateRetour) {
return ($dateRetour - $dateEmprunt).Days
}
$duree = Calculer-DureePret "2023-01-01" "2023-01-15"
Write-Host "Le livre a été emprunté pendant $duree jours."
Explication : Cette fonction calcule la durée de prêt d’un livre en jours. Elle prend deux paramètres (dateEmprunt et dateRetour) et retourne la différence en jours. L’appel de la fonction démontre son utilisation avec des dates spécifiques.
Fonction avec paramètres nommés
function Calculer-DureePret {
param(
[DateTime]$dateEmprunt,
[DateTime]$dateRetour
)
return ($dateRetour - $dateEmprunt).Days
}
$duree = Calculer-DureePret -dateEmprunt "2023-01-01" -dateRetour "2023-01-15"
Explication : Cette version améliorée utilise des paramètres nommés et spécifie explicitement le type DateTime pour chaque paramètre, ce qui améliore la robustesse de la fonction.
Paramètres avancés
Paramètres obligatoires et optionnels
function Ajouter-Livre {
param(
[Parameter(Mandatory=$true)]
[string]$titre,
[Parameter(Mandatory=$true)]
[string]$auteur,
[Parameter(Mandatory=$false)]
[int]$anneePublication = (Get-Date).Year,
[Parameter(Mandatory=$false)]
[string]$genre = "Non spécifié"
)
Write-Host "Nouveau livre ajouté : $titre par $auteur ($anneePublication) - Genre : $genre"
}
Ajouter-Livre -titre "1984" -auteur "George Orwell" -anneePublication 1949 -genre "Science-fiction"
Explication : Cette fonction démontre l’utilisation de paramètres obligatoires (titre et auteur) et optionnels (anneePublication et genre) avec des valeurs par défaut. L’attribut [Parameter] permet de définir ces caractéristiques.
Validation des paramètres
function Ajouter-Livre {
param(
[Parameter(Mandatory=$true)]
[string]$titre,
[Parameter(Mandatory=$true)]
[string]$auteur,
[Parameter(Mandatory=$false)]
[ValidateRange(1000, (Get-Date).Year)]
[int]$anneePublication = (Get-Date).Year,
[Parameter(Mandatory=$false)]
[ValidateSet("Fiction", "Non-fiction", "Science-fiction", "Biographie", "Histoire")]
[string]$genre = "Non spécifié"
)
Write-Host "Nouveau livre ajouté : $titre par $auteur ($anneePublication) - Genre : $genre"
}
Explication : Cette version ajoute une validation des paramètres. ValidateRange assure que l’année de publication est comprise entre 1000 et l’année actuelle. ValidateSet limite les choix de genre à une liste prédéfinie.
Fonctions avancées
Utilisation de CmdletBinding
Options de CmdletBinding
CmdletBinding est un attribut qui transforme une fonction PowerShell en une fonction avancée, lui donnant des fonctionnalités similaires à celles des cmdlets. Voici les principales options disponibles :
1. SupportsShouldProcess
function Supprimer-Fichier {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]$Chemin
)
if ($PSCmdlet.ShouldProcess($Chemin, "Supprimer le fichier")) {
Remove-Item $Chemin
}
}
Cette option permet d’utiliser -WhatIf et -Confirm avec votre fonction. Elle est utile pour les opérations potentiellement dangereuses.
2. ConfirmImpact
function Formater-Disque {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param(
[Parameter(Mandatory=$true)]
[string]$Lecteur
)
if ($PSCmdlet.ShouldProcess($Lecteur, "Formater le disque")) {
# Code pour formater le disque
}
}
ConfirmImpact définit le niveau de risque de l’opération. Les valeurs possibles sont ‘Low’, ‘Medium’, ‘High’.
3. DefaultParameterSetName
Cette option est utile lorsque votre fonction a plusieurs jeux de paramètres et que vous voulez en définir un par défaut.
Exemple détaillé
function Rechercher-Employe {
[CmdletBinding(DefaultParameterSetName='Nom')]
param(
[Parameter(ParameterSetName='Nom', Mandatory=$true, Position=0)]
[string]$Nom,
[Parameter(ParameterSetName='ID', Mandatory=$true)]
[int]$ID,
[Parameter(ParameterSetName='Email', Mandatory=$true)]
[string]$Email
)
switch ($PSCmdlet.ParameterSetName) {
'Nom' {
Write-Host "Recherche par nom : $Nom"
}
'ID' {
Write-Host "Recherche par ID : $ID"
}
'Email' {
Write-Host "Recherche par email : $Email"
}
}
}
# Utilisation du jeu de paramètres par défaut (Nom)
Rechercher-Employe "Dupont"
# Utilisation explicite d'autres jeux de paramètres
Rechercher-Employe -ID 12345
Rechercher-Employe -Email "dupont@entreprise.com"
Dans cet exemple :
- La fonction a trois jeux de paramètres : ‘Nom’, ‘ID’, et ‘Email’.
- DefaultParameterSetName=’Nom’ signifie que si aucun paramètre n’est spécifié, PowerShell utilisera le jeu ‘Nom’.
- Vous pouvez utiliser la fonction avec n’importe lequel des trois paramètres, mais pas simultanément.
- Si vous appelez la fonction sans spécifier de paramètre nommé, elle s’attendra à recevoir un nom (jeu par défaut).
Cette approche est utile lorsque vous voulez offrir différentes façons de rechercher un employé, tout en ayant une méthode préférée (ici, par nom).
4.PositionalBinding
L’option PositionalBinding contrôle si les paramètres de votre fonction peuvent être utilisés de manière positionnelle (sans spécifier le nom du paramètre) ou non.
Exemple avec PositionalBinding=$true (valeur par défaut)
function Test-PositionalBinding {
[CmdletBinding(PositionalBinding=$true)]
param(
[Parameter(Position=0)]
[string]$Param1,
[Parameter(Position=1)]
[int]$Param2
)
Write-Host "Param1: $Param1, Param2: $Param2"
}
# Ces deux appels sont équivalents :
Test-PositionalBinding "Bonjour" 42
Test-PositionalBinding -Param1 "Bonjour" -Param2 42
Dans cet exemple, vous pouvez utiliser les paramètres de manière positionnelle ou nommée.
Exemple avec PositionalBinding=$false
function Test-NonPositionalBinding {
[CmdletBinding(PositionalBinding=$false)]
param(
[Parameter()]
[string]$Param1,
[Parameter()]
[int]$Param2
)
Write-Host "Param1: $Param1, Param2: $Param2"
}
# Cet appel fonctionne :
Test-NonPositionalBinding -Param1 "Bonjour" -Param2 42
# Cet appel ne fonctionnera pas comme prévu :
Test-NonPositionalBinding "Bonjour" 42 # Erreur : les paramètres ne sont pas reconnus
Avec PositionalBinding=$false, vous devez obligatoirement utiliser les noms des paramètres.
5. HelpUri
function Get-InfoSysteme {
[CmdletBinding(HelpUri='https://mon-site.com/aide/get-infosysteme')]
param()
# Code pour obtenir les informations système
}
Cette option permet de spécifier une URL vers une page d’aide en ligne pour votre fonction.
Conclusion CmdletBinding
Ces options de CmdletBinding permettent de créer des fonctions PowerShell avancées avec un comportement similaire aux cmdlets natifs. Elles offrent une meilleure gestion des paramètres, des confirmations d’actions, et une intégration plus poussée avec l’environnement PowerShell.
Pour votre site modern-workplace.fr, ces exemples pourraient être utiles pour illustrer comment créer des fonctions PowerShell robustes et professionnelles dans le contexte de Microsoft 365 et de l’administration système.
function Rechercher-Livre {
[CmdletBinding()]
param(
[Parameter(Mandatory=$false, Position=0)]
[string]$titre,
[Parameter(Mandatory=$false)]
[string]$auteur,
[Parameter(Mandatory=$false)]
[switch]$disponible
)
begin {
Write-Verbose "Début de la recherche de livres..."
}
process {
$message = "Recherche de livres"
if ($titre) { $message += " avec le titre '$titre'" }
if ($auteur) { $message += " de l'auteur '$auteur'" }
if ($disponible) { $message += " actuellement disponibles" }
Write-Verbose $message
}
end {
Write-Verbose "Fin de la recherche de livres."
}
}
Rechercher-Livre -titre "1984" -auteur "Orwell" -disponible -Verbose
Explication : Cette fonction utilise CmdletBinding pour la transformer en une fonction avancée. Elle utilise les blocs begin, process et end pour structurer le traitement, et Write-Verbose pour fournir des informations détaillées lorsque -Verbose est utilisé.
Utilisation de pipeline
function Afficher-InfoLivre {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[PSCustomObject]$livre
)
process {
Write-Host "Titre: $($livre.Titre)"
Write-Host "Auteur: $($livre.Auteur)"
Write-Host "Année: $($livre.AnneePublication)"
Write-Host "Genre: $($livre.Genre)"
Write-Host "---"
}
}
$livres = @(
[PSCustomObject]@{Titre="1984"; Auteur="George Orwell"; AnneePublication=1949; Genre="Science-fiction"},
[PSCustomObject]@{Titre="Le Petit Prince"; Auteur="Antoine de Saint-Exupéry"; AnneePublication=1943; Genre="Fiction"}
)
$livres | Afficher-InfoLivre
Explication : Cette fonction accepte des entrées via le pipeline grâce à ValueFromPipeline et ValueFromPipelineByPropertyName. Elle traite chaque livre passé dans le pipeline et affiche ses informations.

Gestion avancée des fonctions
Alias de fonction
New-Alias -Name rl -Value Rechercher-Livre
rl -titre "1984" -Verbose
Explication : Cette commande crée un alias ‘rl’ pour la fonction Rechercher-Livre, permettant de l’appeler plus rapidement.
Exportation de fonctions
function Export-BiblioFunctions {
Export-ModuleMember -Function Ajouter-Livre, Rechercher-Livre, Afficher-InfoLivre
Export-ModuleMember -Alias rl
}
Explication : Cette fonction exporte les fonctions et alias spécifiés, les rendant disponibles lorsque le module est importé dans d’autres scripts.
Utilisation de DynamicParam
function Emprunter-Livre {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$titre
)
DynamicParam {
$paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$livresDisponibles = (Get-Content "livres_disponibles.json" -Encoding UTF8 | ConvertFrom-Json).Livres
$attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
$paramAttribute = New-Object System.Management.Automation.ParameterAttribute
$paramAttribute.Mandatory = $true
$paramAttribute.ParameterSetName = "__AllParameterSets"
$attributeCollection.Add($paramAttribute)
$titresASCII = $livresDisponibles.Titre | ForEach-Object {
[Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($_))
}
$validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute([string[]]$titresASCII)
$attributeCollection.Add($validateSetAttribute)
$dynParam = New-Object System.Management.Automation.RuntimeDefinedParameter("LivreDisponible", [string], $attributeCollection)
$paramDictionary.Add("LivreDisponible", $dynParam)
return $paramDictionary
}
process {
$livreChoisi = $PSBoundParameters["LivreDisponible"]
$livreTrouve = $livresDisponibles | Where-Object {
[Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($_.Titre)) -eq $livreChoisi
}
Write-Host "Vous avez emprunté le livre : $($livreTrouve.Titre)"
}
}
Explication : Cette fonction utilise DynamicParam pour créer un paramètre dynamique basé sur le contenu d’un fichier JSON. Cela permet de valider le choix du livre contre une liste de livres disponibles qui peut changer dynamiquement.
{
"Livres": [
{
"Titre": "1984",
"Auteur": "George Orwell",
"Année": 1949
},
{
"Titre": "Le Petit Prince",
"Auteur": "Antoine de Saint-Exupéry",
"Année": 1943
},
{
"Titre": "Cent ans de solitude",
"Auteur": "Gabriel GarcÃa Márquez",
"Année": 1967
},
{
"Titre": "L'Étranger",
"Auteur": "Albert Camus",
"Année": 1942
},
{
"Titre": "Harry Potter à l'école des sorciers",
"Auteur": "J.K. Rowling",
"Année": 1997
},
{
"Titre": "Le Seigneur des Anneaux",
"Auteur": "J.R.R. Tolkien",
"Année": 1954
},
{
"Titre": "Orgueil et Préjugés",
"Auteur": "Jane Austen",
"Année": 1813
},
{
"Titre": "Crime et Châtiment",
"Auteur": "Fiodor Dostoïevski",
"Année": 1866
},
{
"Titre": "Le Comte de Monte-Cristo",
"Auteur": "Alexandre Dumas",
"Année": 1844
},
{
"Titre": "Les Misérables",
"Auteur": "Victor Hugo",
"Année": 1862
}
]
}
Conclusion
Les fonctions en PowerShell offrent une grande flexibilité et puissance pour automatiser et simplifier la gestion d’une bibliothèque numérique. En utilisant des paramètres avancés, la validation, le pipeline et des techniques comme CmdletBinding et DynamicParam, nous pouvons créer des outils robustes et flexibles pour gérer efficacement notre collection de livres.