Maîtrise des fonctions PowerShell : Un guide étape par étape

Une fois que vous vous êtes habitué à écrire des scripts PowerShell, vous devez apprendre la modularisation du code. La modularisation est simplement un terme sophistiqué pour créer du code en blocs de construction. Dans le monde de PowerShell, les fonctions PowerShell sont l’un des meilleurs moyens de le faire.

Lorsque vous écrivez un script PowerShell, vous avez de nombreuses options pour écrire le code. Vous pourriez écrire mille lignes de code qui effectuent des centaines de tâches, le tout dans un seul bloc de code ininterrompu. Ce serait un désastre. Au lieu de cela, vous devriez écrire des fonctions.

Les fonctions augmentent considérablement la convivialité et la lisibilité de votre code, ce qui le rend beaucoup plus facile à manipuler. Dans ce tutoriel, vous apprendrez à écrire des fonctions, à ajouter et à gérer les paramètres de vos fonctions, et à configurer les fonctions pour accepter une entrée en pipeline. Mais d’abord, examinons un peu de terminologie.

Cet article a été extrait de mon livre PowerShell pour les administrateurs système : Automatisation des flux de travail simplifiée. Si vous apprenez quelque chose dans ce tutoriel, assurez-vous de consulter le livre pour en savoir plus sur les fonctions et bien d’autres fonctionnalités intéressantes de PowerShell.

Fonctions vs Cmdlets

Le concept d’une fonction peut sembler familier car il ressemble un peu aux cmdlets que vous avez probablement déjà utilisés. Des commandes telles que Start-Service et Write-Host, par exemple, sont similaires aux fonctions. Ce sont des morceaux de code nommés qui résolvent un seul problème. La différence entre une fonction et un cmdlet réside dans la façon dont chacune de ces constructions est réalisée.

A cmdlet isn’t written with PowerShell. It’s written in another language, typically something like C#. The cmdlet is then compiled and made available inside PowerShell.

Les fonctions, en revanche, sont écrites en PowerShell, pas dans un autre langage.

Vous pouvez voir quelles commandes sont des cmdlets et quelles sont des fonctions en utilisant la cmdlet Get-Command et son paramètre CommandType comme indiqué ci-dessous

Get-Command –CommandType Function

Cette commande ci-dessus renvoie toutes les fonctions actuellement chargées dans votre session PowerShell, ou dans des modules disponibles pour PowerShell.

Connexe: Comprendre et créer des modules PowerShell

Prérequis

Si vous souhaitez suivre tous les exemples, assurez-vous d’avoir une version de PowerShell disponible. Il n’y a pas d’exigences de version spécifiques pour ce tutoriel. Assurez-vous également d’avoir un bon éditeur de code comme Visual Studio Code pour copier, coller et exécuter quelques extraits de code.

Construction d’une fonction simple

Avant de pouvoir utiliser une fonction, vous devez la définir. Pour définir une fonction, vous utilisez le mot-clé « function », suivi d’un nom descriptif défini par l’utilisateur, suivi d’un ensemble d’accolades. À l’intérieur des accolades se trouve un bloc de script que vous souhaitez que PowerShell exécute.

Vous pouvez voir ci-dessous une fonction de base et l’exécution de cette fonction. Cette fonction appelée Install-Software utilise Write-Host pour afficher un message dans la console. Une fois qu’elle est définie, vous pouvez utiliser le nom de cette fonction pour exécuter le code à l’intérieur de son bloc de script.

PS> function Install-Software { Write-Host 'I installed some software. Yippee!' }
PS> Install-Software
I installed some software, Yippee!

Nommage avec un verbe et un nom

A function’s name is important. You can name your functions whatever you want, but the name should always describe what the function does. The function-naming convention in PowerShell is the Verb-Noun syntax.

Vous devriez toujours commencer le nom d’une fonction par un verbe suivi d’un tiret et d’un nom. Pour trouver la liste des verbes « approuvés », utilisez la cmdlet Get-Verb.

Modifier le comportement d’une fonction

Si vous souhaitez modifier le comportement d’une fonction, vous pouvez simplement modifier le code que la fonction exécute, comme indiqué ci-dessous.

PS> function Install-Software { Write-Host 'You installed some software, Yay!' }
PS> Install-Software
You installed some software, Yay!

Maintenant que vous avez modifié le code à l’intérieur de la fonction, elle affichera un message légèrement différent.

Définition d’une fonction avancée

Vous pouvez définir des fonctions à de nombreux endroits différents. Dans la section précédente, le tutoriel suppose que vous avez simplement copié et collé le code directement dans la console PowerShell. Mais ce n’est pas la seule façon. Vous pouvez également définir des fonctions dans un script.

Dans la section précédente, vous travailliez avec une petite fonction, donc la définir dans la console n’était pas vraiment un problème. La plupart du temps cependant, vous aurez des fonctions beaucoup plus grandes. Il sera plus facile de définir ces fonctions dans un script ou un module, puis d’appeler ce script ou ce module pour charger la fonction en mémoire.

Comme vous pouvez l’imaginer, retaper une fonction plus grande à chaque fois que vous souhaitez ajuster sa fonctionnalité peut devenir un peu frustrant.

I suggest you now open your favorite editor and store the function in a .ps1 file as you work through the rest of the tutorial.

Ajout de paramètres aux fonctions

Les fonctions PowerShell peuvent avoir un nombre quelconque de paramètres. Lorsque vous créez vos propres fonctions, vous avez la possibilité d’inclure des paramètres et de décider comment ces paramètres fonctionnent. Les paramètres peuvent être obligatoires ou facultatifs, et ils peuvent accepter n’importe quoi ou être contraints d’accepter l’un des arguments possibles d’une liste limitée.

Lié : Tout ce que vous avez toujours voulu savoir sur les paramètres PowerShell

Par exemple, le logiciel fictif que vous installez via la fonction Install-Software précédente pourrait avoir de nombreuses versions. Mais actuellement, la fonction Install-Software ne propose aucun moyen à l’utilisateur de spécifier quelle version il souhaite installer.

Si vous étiez le seul à utiliser la fonction, vous pourriez modifier le code à l’intérieur chaque fois que vous vouliez une version spécifique, mais cela serait une perte de temps. Ce processus serait également sujet à des erreurs potentielles, sans parler du fait que vous souhaitez que d’autres puissent utiliser votre code.

L’introduction de paramètres dans votre fonction lui permet d’avoir une variabilité. Tout comme les variables vous ont permis d’écrire des scripts capables de gérer de nombreuses versions de la même situation, les paramètres vous permettent d’écrire une seule fonction qui fait une chose de nombreuses façons.

Dans ce cas, vous souhaitez installer des versions du même logiciel, et ce, sur de nombreux ordinateurs.

Commençons par ajouter un paramètre à la fonction qui vous permet ou à l’utilisateur de spécifier la version à installer.

Création d’un paramètre simple

La création d’un paramètre sur une fonction nécessite un bloc param. Le bloc param contient tous les paramètres de la fonction. Définissez un bloc param avec le mot-clé param suivi de parenthèses comme indiqué ci-dessous.

function Install-Software {
	[CmdletBinding()]
	param()

	Write-Host 'I installed software version 2. Yippee!'
}

À ce stade, la fonction n’a pas encore changé de fonctionnalité. Vous avez simplement installé la plomberie, préparant la fonction pour un paramètre.

Pour l’instant, la fonction n’installe pas réellement de logiciel. Elle utilise simplement la commande Write-Host pour simuler l’installation du logiciel afin que vous puissiez vous concentrer sur l’écriture de la fonction.

Une fois que vous avez ajouté le bloc param, vous pouvez créer le paramètre en le plaçant entre les parenthèses du bloc param comme indiqué ci-dessous.

function Install-Software {
	[CmdletBinding()]
	param(
		[Parameter()]
		[string] $Version
	)
	
	Write-Host "I installed software version $Version. Yippee!"

}

Dans le bloc param ci-dessus, vous définiriez d’abord le bloc Paramètre. Utiliser le bloc Parameter() de cette manière le transformera en « paramètre avancé ». Un bloc Paramètre vide comme celui-ci ne fait rien mais est requis ; je vous expliquerai comment l’utiliser dans la section suivante.

Concentrons-nous plutôt sur le type [string] devant le nom du paramètre. En mettant le type du paramètre entre crochets avant le nom de la variable du paramètre, vous effectuez une conversion de la valeur du paramètre vers un type spécifique. PowerShell essaiera toujours de convertir toute valeur passée à ce paramètre en une chaîne de caractères, si ce n’en est pas déjà une. Dans l’exemple ci-dessus, tout ce qui est passé en tant que $Version sera toujours traité comme une chaîne de caractères.

Il n’est pas obligatoire de convertir votre paramètre en un type, mais je vous encourage fortement à le faire. Cela définit explicitement le type et réduira considérablement les erreurs à l’avenir.

Vous ajoutez également $Version dans votre instruction Write-Host maintenant. Cela signifie que lorsque vous exécutez la fonction Install-Software avec le paramètre Version et lui passez un numéro de version, vous devriez obtenir une instruction en conséquence comme indiqué ci-dessous.

PS> Install-Software -Version 2
I installed software version 2. Yippee!

Voyons maintenant ce que vous pouvez faire avec ce paramètre.

L’attribut de paramètre obligatoire

Vous pouvez utiliser le bloc de paramètres pour contrôler divers attributs de paramètres, ce qui vous permettra de modifier le comportement du paramètre. Par exemple, si vous souhaitez vous assurer que toute personne appelant la fonction doit fournir un paramètre donné, vous pouvez définir ce paramètre comme obligatoire.

Par défaut, les paramètres sont facultatifs. Forçons l’utilisateur à fournir une version en utilisant le mot clé « Mandatory » à l’intérieur du bloc de paramètres comme indiqué ci-dessous.

function Install-Software {
	[CmdletBinding()]
	param(
		[Parameter(Mandatory)]
		[string]$Version
	)

	Write-Host "I installed software version $Version. Yippee!"

}

Si vous exécutez la fonction ci-dessus, vous devriez obtenir l’invite suivante :

Prompting for a mandatory parameter

Une fois que vous avez défini l’attribut Obligatoire, l’exécution de la fonction sans le paramètre interrompra l’exécution jusqu’à ce que l’utilisateur saisisse une valeur. La fonction attend maintenant que l’utilisateur spécifie une valeur pour le paramètre Version. Une fois saisie, PowerShell exécute la fonction.

Pour éviter l’invite du paramètre obligatoire, il suffit de passer une valeur au paramètre lors de l’appel de la fonction comme indiqué ci-dessous.

Install-Software -Version 2

Valeurs par défaut des paramètres

Par exemple, si vous vous trouvez à passer la même valeur pour un paramètre encore et encore, vous pouvez définir une valeur par défaut pour le paramètre. Les paramètres par défaut sont utiles lorsque vous vous attendez à une certaine valeur pour un paramètre la plupart du temps.

Par exemple, si vous souhaitez installer la version 2 de ce logiciel 90% du temps et que vous ne souhaitez pas avoir à définir la valeur à chaque fois que vous exécutez cette fonction, vous pouvez attribuer une valeur par défaut de 2 au paramètre $Version. Vous pouvez voir cet exemple ci-dessous.

function Install-Software {
	[CmdletBinding()]
	param(
		[Parameter()]
		[string]$Version = 2
	)

	Write-Host "I installed software version $Version. Yippee!"

}

Avoir un paramètre par défaut ne vous empêche pas d’en passer un. Votre valeur passée en surchargera la valeur par défaut.

Ajout d’attributs de validation de paramètres

Il est toujours bon de limiter les valeurs que vous pouvez passer à une fonction via des paramètres. La meilleure façon de le faire est avec des attributs de validation de paramètres.

Limiter les informations que les utilisateurs (ou même vous-même !) peuvent passer à vos fonctions ou scripts éliminera du code inutile à l’intérieur de votre fonction. Par exemple, supposons que vous passez la valeur 3 à votre fonction Install-Software, sachant que la version 3 est une version existante.

Votre fonction suppose que chaque utilisateur sait quelles versions existent, elle ne tient donc pas compte de ce qui se passe lorsque vous essayez de spécifier la version 4. Dans ce cas, la fonction échouera à trouver le dossier approprié car il n’existe pas.

La vie sans validation de paramètres

Jetez un coup d’œil à l’exemple ci-dessous lorsque vous utilisez la chaîne $Version dans un chemin de fichier. Si quelqu’un passe une valeur qui ne correspond pas à un nom de dossier existant (par exemple, SoftwareV3 ou SoftwareV4), le code échouera.

function Install-Software {
	param(
		[Parameter(Mandatory)]
		[string]$Version
	)

	Get-ChildItem -Path \\SRV1\Installers\SoftwareV$Version

}
Failing on unexpected parameter values

Vous pourriez écrire du code de gestion des erreurs pour résoudre ce problème, ou vous pourriez éliminer le problème en exigeant que l’utilisateur ne passe qu’une version existante du logiciel. Pour limiter la saisie de l’utilisateur, ajoutez une validation des paramètres.

Ajout de la validation des paramètres

Il existe différentes formes de validation des paramètres, mais en ce qui concerne votre fonction Install-Software, l’attribut [ValidateSet](https://adamtheautomator.com/powershell-validateset/) fonctionne le mieux. L’attribut de validation ValidateSet vous permet de spécifier une liste de valeurs autorisées pour le paramètre. Si vous ne prenez en compte que la chaîne 1 ou 2, vous vous assurez que l’utilisateur ne puisse spécifier que ces valeurs ; sinon, la fonction échouera immédiatement et informera l’utilisateur du problème.

Ajoutez les attributs de validation des paramètres à l’intérieur du bloc param, juste en dessous du bloc Parameter d’origine, comme indiqué ci-dessous.

function Install-Software {
	param(
		[Parameter(Mandatory)]
		[ValidateSet('1','2')]
		[string]$Version
	)

	Get-ChildItem -Path \\SRV1\Installers\SoftwareV$Version

}

En ajoutant un ensemble d’éléments (1 et 2) à l’intérieur des parenthèses finales de l’attribut ValidateSet, cela indique à PowerShell que les seules valeurs valides pour Version sont 1 ou 2. Si un utilisateur essaie de passer autre chose que ce qui est dans l’ensemble, il recevra un message d’erreur comme indiqué ci-dessous, l’informant qu’il n’a qu’un nombre spécifique d’options disponibles.

Parameter validation stopping PowerShell function execution

L’attribut ValidateSet est un attribut de validation courant, mais d’autres sont disponibles. Pour une explication complète de toutes les façons dont les valeurs des paramètres peuvent être restreintes, consultez la documentation Microsoft.

Accepter une entrée de pipeline

Jusqu’à présent, vous avez créé une fonction avec un paramètre qui peut être passé uniquement en utilisant la syntaxe habituelle -NomDuParamètre <Valeur>. Cela fonctionne, mais vous avez également une autre option pour passer des valeurs aux paramètres en utilisant le pipeline PowerShell. Ajoutons des capacités de pipeline à notre fonction Install-Software.

Lié : Accepter une entrée de pipeline dans l’article sur les paramètres ATA PowerShell

Tout d’abord, ajoutez un autre paramètre à votre code qui spécifie l’ordinateur sur lequel vous souhaitez installer le logiciel. Ajoutez également ce paramètre à votre référence Write-Host pour simuler l’installation.

function Install-Software {
	param(
		[Parameter(Mandatory)]
		[string]$Version
		[ValidateSet('1','2')],
		
		[Parameter(Mandatory)]
		[string]$ComputerName
	)

	Write-Host "I installed software version $Version on $ComputerName. Yippee!"

}

Une fois que vous avez ajouté le paramètre ComputerName à la fonction, vous pouvez maintenant itérer sur une liste de noms d’ordinateurs et passer les valeurs du nom de l’ordinateur et de la version à la fonction Install-Software, comme indiqué ci-dessous.

$computers = @("SRV1", "SRV2", "SRV3")
foreach ($pc in $computers) {
	Install-Software -Version 2 -ComputerName $pc
}

Au lieu de faire tout cela, vous devriez apprendre à utiliser le pipeline à la place.

Rendre la fonction compatible avec le pipeline

Malheureusement, vous ne pouvez pas profiter du pipeline PowerShell avec une simple fonction construite précédemment. Vous devez décider du type d’entrée de pipeline que vous souhaitez que la fonction accepte et l’implémenter.

A PowerShell function uses two kinds of pipeline input: ByValue (entire object) and ByPropertyName (a single object property). Here, because the $computers array contains only strings, you’ll pass those strings via ByValue.

Pour ajouter la prise en charge du pipeline, ajoutez un attribut de paramètre au paramètre souhaité en utilisant l’un des deux mots-clés : ValueFromPipeline ou ValueFromPipelineByPropertyName comme indiqué ci-dessous.

function Install-Software {
	param(
		[Parameter(Mandatory)]
		[ValidateSet('1','2')]
		[string]$Version,

		[Parameter(Mandatory, ValueFromPipeline)]
		[string]$ComputerName
	)

	Write-Host "I installed software version $Version on $ComputerName. Yippee!"

}

Une fois que vous avez chargé la fonction Install-Software mise à jour, appelez-la comme ceci :

$computers = @("SRV1", "SRV2", "SRV3")
$computers | Install-Software -Version 2

Exécutez à nouveau le script et vous devriez obtenir quelque chose comme ceci :

I installed software version 2 on SRV3. Yippee!

Remarquez que Install-Software s’exécute uniquement pour la dernière chaîne du tableau. Vous verrez comment corriger cela dans la section suivante.

Ajout d’un bloc de traitement

Pour indiquer à PowerShell d’exécuter cette fonction pour chaque objet qui entre, vous devez inclure un bloc de traitement. À l’intérieur du bloc de traitement, placez le code que vous souhaitez exécuter à chaque fois que la fonction reçoit une entrée de pipeline. Ajoutez un bloc de traitement à votre script comme indiqué ci-dessous.

function Install-Software {
	param(
		[Parameter(Mandatory)]
		[ValidateSet('1','2')]
		[string]$Version,

		[Parameter(Mandatory, ValueFromPipeline)]
		[string]$ComputerName
	)

	process {
		Write-Host "I installed software version $Version on $ComputerName. Yippee!"
	}
}

Maintenant, appelez à nouveau la fonction comme vous l’avez fait précédemment. La fonction Install-Software renverra maintenant trois lignes (une pour chaque objet).

I installed software version 2 on SRV1. Yippee!
I installed software version 2 on SRV2. Yippee!
I installed software version 2 on SRV3. Yippee!

Le bloc de traitement contient le code principal que vous souhaitez exécuter. Vous pouvez également utiliser les blocs begin et end pour le code qui s’exécutera au début et à la fin de l’appel de la fonction. Vous pouvez en savoir plus sur les blocs begin, process et end via la documentation Microsoft.

Étapes suivantes

Les fonctions vous permettent de compartimenter le code en blocs de construction distincts. Elles vous aident non seulement à diviser votre travail en morceaux plus petits et plus gérables, mais elles vous obligent également à écrire un code lisible et testable.

I now challenge you to look through some old scripts and see where you can add a PowerShell function. Look for patterns in code. Build a function from those patterns. Notice where you’re copying/pasting code snippets and turn those into PowerShell functions!

Source:
https://adamtheautomator.com/powershell-functions/