Utiliser les Parameter Sets !

Posted by : at

Category : PowerShell   Niv200


Définition

Les jeux de paramètres permettent de définir un ensemble de paramètre qui doivent être utiliser par une fonction.

Cela permet par exemple de définir pour une même fonction 2 paramètres différents en entrée. Dans cette article nous allons voir comment, par exemple, faire une fonction New-MyADUser avec comme paramètre soit un ensemble de nom soit un fichier.

Fonction avec utilisateur en entrée

Cette fonction est assez basique. Elle va prendre en paramètre d’entrée une liste de nom d’utilisateur a créer.

function New-MyADUser {
    param (
        [System.String[]]$UserName
    )

    foreach($User in $UserName) {
        New-ADUser -Name $User -GivenName ($User.Split(".")[0]) -Surname ($User.Split(".")[1])
    }

}

Ensuite je peux lancer la création de mes utilisateurs

New-MyADUser -UserName "Utilisateur1.Test","Utilisateur2.Test","Utilisateur3.Test"

Fonction avec un fichier en entrée

Dans ce cas nous allons reprendre la même fonction mais avec en entrée la liste des noms dans un fichier csv.

function New-MyADUser {
    param (
        [System.String]$FileName
    )

    $UserName = Import-Csv -Path $FileName

    foreach ($User in $UserName) {
        New-ADUser -name $User.UserName -GivenName ($User.UserName.Split(".")[0]) -Surname ($User.UserName.Split(".")[1])
    }

}

Ensuite je peux lancer la création de mes utilisateurs

New-MyADUser -FileName '.\Utiliser les Parameter Sets\Utilisateurs.csv'

Donc maintenant nous avons 2 fonctions différentes mais qui font sensiblement la même chose : créer des utilisateurs dans l’Active Directory

C’est la que rentre en jeu les jeux de paramètres. Nous allons immédiatement voir ca :-)

Fonction avec un fichier ou un utilisateur en entrée

ParameterSetName

Le but donc est de combiner ces 2 fonctions en une seule mais acceptant les 2 types de paramètre en entrée.

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName='ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.String]$FileName
    )
}

Première étape je combine les 2 paramètres en leur affectant un nom de jeux de paramètres (ParameterSetName).

Pour ce faire vous avez du remarquer l’ajout de CmdletBinding. Pour pouvoir utiliser la commande ParameterSetName il faut passer par une fonction avancée

Naturellement il faut donner un nom différent au 2 jeux de paramètres pour pouvoir, plus tard les différencier.

Si je fais

 Get-Command -Name New-MyADUser -Syntax

New-MyADUser [-UserName <string[]>] [<CommonParameters>]
New-MyADUser [-FileName <string>] [<CommonParameters>]

On peut voir que j’ai bien 2 façons d’appeler ma fonction avec le Username ou le FileName les 2 étant exclusif c’est a dire que je ne peux pas faire

 New-MyADUser -UserName $UserName -FileName $FileName

New-MyADUser : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ New-MyADUser -UserName $UserName -FileName $FileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-MyADUser], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,New-MyADUser

La commande ne peut pas trouver quel jeu de paramètre elle doit executer.

Bon maintenant que je peux appeler ma fonction avec les 2 types de paramètre comment faire dans la fonction pour traiter chacun des paramètres.

$PSCmdlet.ParameterSetName

Grâce a cette ligne de commande nous pouvons récupérer le nom du jeu de paramètre utilisé, ByUserName ou ByFileName dans notre cas, et grâce a cela faire un traitement différent selon le paramètre passé à la fonction.

Ajoutons cette ligne de commande a notre fonction

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName='ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.String]$FileName
    )

    $PSCmdlet.ParameterSetName
}

Si je fait New-MyADUser -Username "Utilisateur.Test" le résultat sera

 New-MyADUser -UserName "Utilisateur.test"

ByUserName

Si je fait New-MyADUser -FileName ".\Utiliser les Parameter Sets\Utilisateurs.csv" le résultat sera

 New-MyADUser -FileName ".\Utiliser les Parameter Sets\Utilisateurs.csv"

ByFileName

Effectivement le paramètre UserName fait bien parti du jeu de paramètre ByUserName et FileName du jeu de paramètre ByFileName

Ok donc maintenant nous savons différencier les 2 cas grâce à $PSCmdlet.ParameterSetName. Il ne nous reste plus qu’a effectuer le traitement adéquat en fonction du cas.

Pour ce faire nous allons simplement ajouter une commande switch dans notre fonction et copier le contenu de nos 2 fonctions précédentes

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName='ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.IO.DirectoryInfo]$FileName
    )

    switch ($PSCmdlet.ParameterSetName) {
        "ByUserName" {
            $PSCmdlet.ParameterSetName
            foreach ($User in $UserName) {
                New-ADUser -name $User -GivenName ($User.Split(".")[0]) -Surname ($User.Split(".")[1])
            }
         }
        "ByFileName" {
            $PSCmdlet.ParameterSetName
            $UserName = Import-Csv -Path $FileName
            foreach ($User in $UserName) {
                New-ADUser -name $User.UserName -GivenName ($User.UserName.Split(".")[0]) -Surname ($User.UserName.Split(".")[1])
            }
         }
    }
}
Cette fonction pourrait encore être simplifiée mais ce n'est pas l'objet de cet article

Voilà comment faire pour l’utilisation des jeux de paramètres

Si vous avez des questions ou …

Attendez ! je suis sur que vous vous en posez une dès à présent !

Si! Si!

Vous savez la fameuse question : Comment je fais si un paramètre doit faire parti des 2 jeux de paramètres en même temps ?

Nous allons tenter d’y répondre ;-)

Un paramètre dans plusieurs jeux de paramètres

Bon la plus logique des approches si vous avez compris le principe serait de faire

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName = 'ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByUserName')]
        [System.String]$Password,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.IO.DirectoryInfo]$FileName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.String]$Password
    )
}

mais l’execution de ce code retourne l’erreur

Duplicate parameter $Password in parameter list.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : DuplicateFormalParameter

Donc on ne peut pas mettre 2 fois le même nom de paramètre !

Soit! Je ne peux pas définir 2 paramètres identiques dans 2 jeux de paramètre distinct, mais est-ce que je peux définir 1 paramètre qui sera disponible dans les 2 jeux ?

et si on essayait cela

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName = 'ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.IO.DirectoryInfo]$FileName,

        [Parameter(ParameterSetName = 'ByUserName')]
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.String]$Password
    )
}

Déjà l’execution de ce code ne retourne pas d’erreur : un bon point !

Regardons la syntaxe de la fonction maintenant

  Get-Command -Name New-MyADUser -Syntax

New-MyADUser [-UserName <string[]>] [-Password <string>] [<CommonParameters>]
New-MyADUser [-FileName <DirectoryInfo>] [-Password <string>] [<CommonParameters>]

Le paramètre password se retrouve bien dans les 2 jeux de paramètres : VICTOIRE !

En extrapolant un peu, on peu s’imaginer avoir plusieurs jeux de paramètres pour une fonction. il semble évident que cela va être compliqué de mettre un paramètre dans tous les jeux de paramètres de cette façon.

Et si pour simplifier nous le mettions tous simplement dans aucun !

function New-MyADUser {
    [CmdletBinding(DefaultParameterSetName = "ByUserName")]
    param (
        [Parameter(ParameterSetName = 'ByUserName')]
        [System.String[]]$UserName,
        [Parameter(ParameterSetName = 'ByFileName')]
        [System.IO.DirectoryInfo]$FileName,

        [System.String]$Password
    )
}

Le résultat est le suivant :

 Get-Command -Name New-MyADUser -Syntax


New-MyADUser [-UserName <string[]>] [-Password <string>] [<CommonParameters>]

New-MyADUser [-FileName <DirectoryInfo>] [-Password <string>] [<CommonParameters>]

Le paramètre passwordest toujours membre des 2 jeux de paramètre.

Il suffit donc de n’affecter un paramètre a AUCUN jeux de paramètres pour qu’il soit commun à TOUS les jeux de paramètres.

Conclusion

Nous avons donc vu dans cet article :

  • Qu’est-ce que c’est qu’un jeu de paramètres
  • A quoi sert un jeu de paramètres
  • Comment affecter un paramètre à plusieurs jeux de paramètres
  • Comment affecter un paramètre a tous les jeux de paramètres

les exemples de code sont disponible sur le Github

Si vous avez des questions, si je me suis trompé sur un point ou simplement échanger avec moi n’hésitez pas à me contacter sur les réseaux sociaux.


About LIENHARD Laurent
LIENHARD Laurent

Email : laurent@lienhard.fr

Website :

About LIENHARD Laurent

Auto-Didacte en PowerShell, Co-fondateur et animateur du French PowerShell & DevOps UserGroup

Useful Links