Qu'est-ce que Windows PowerShell et que mange-t-il? Partie 3: passer des paramètres aux scripts et aux fonctions, créer des applets de commande



La deuxième partie de la série a couvert les bases du langage de programmation PowerShell, mais maintenant il vaut la peine de comprendre comment utiliser le code écrit dessus pour des tâches administratives. La façon la plus évidente de le faire est d'exécuter le script. En plus de cela, il est possible de créer vos propres applets de commande.

Table des matières:


Paramètres positionnels
Bloc Param ()
Attributs de paramètres supplémentaires
Passage de paramètres via le pipeline
Structure du corps de la fonction
Attribut [CmdletBinding ()] et fonctions avancées
Scripting modules et création d'applets de commande

Paramètres positionnels


Dans les scripts et les fonctions, vous pouvez passer des paramètres positionnels (arguments) dont les valeurs sont écrites dans la variable intégrée $ args. Ce tableau unidimensionnel ne nécessite pas de déclaration préalable et sa portée est limitée à un script ou une fonction. Par exemple, exécutez le script le plus simple:

Write-Host " :" $args.count
Write-Host ":" $args


image

Dans les fonctions, les paramètres positionnels sont utilisés de la même manière:

function Print-Args {
    Write-Host " :" $args.count
    Write-Host " 0:" $args[0]
    Write-Host " 1:" $args[1] 
}

Print-Args "Zero" "One"

Veuillez noter que lorsque vous appelez Print-Args, nous ne mettons pas de virgule entre les paramètres: ce n'est pas un tableau qui est transmis à la fonction, mais des valeurs individuelles qui sont écrites dans le tableau unidimensionnel $ args - sa portée est limitée par le corps de la fonction.

image

La méthode décrite ci-dessus vous permet de passer n'importe quel nombre de paramètres à un script ou une fonction, mais lors de l'appel, vous devez suivre l'ordre de leur séquence, et vous ne pouvez y accéder que par l'index du tableau - ce n'est pas toujours pratique.

Bloc de paramètres ()


Dans les scripts et les fonctions, il est beaucoup plus pratique d'utiliser des paramètres nommés. Dans un article précédent, nous avons parlé d'une façon de les décrire:

function test ($arg0, ..., $argN)
{
       
}

Une syntaxe similaire est familière aux développeurs, mais lorsqu'une fonction est appelée, les paramètres (le cas échéant) sont séparés par des espaces et ne sont pas placés entre parenthèses - une certaine dissonance apparaît. C'est la spécificité des langages shell: pour travailler avec le shell en mode interactif, les espaces entre les valeurs sont beaucoup plus pratiques. L' appel test ($ value0) est également correct, mais le paramètre dans ce cas est l'expression entière entre parenthèses, c'est-à-dire ($ value0) au lieu de $ value0 . Passer de cette manière plusieurs paramètres ne fonctionnera pas. À la suite de l'appel de test ($ value0, $ value1), la fonction n'en recevra qu'un - un tableau de deux éléments avec les valeurs $ value0 et $ value1 .

Microsoft Corporation recommande d'utiliser le bloc Param () - cette syntaxe est plus universelle et vous permet de spécifier non seulement des arguments de fonction, mais également des paramètres de script:

param (
    $arg0, $arg1
)

Write-Host $arg0 $arg1


image

Dans le corps de la fonction, cela ressemble à ceci:

function test {
     param (
           $arg0, $arg1
     )
}

Si la liste d'arguments de la fonction est petite, le bloc Param () ne fera qu'encombrer la conception, mais dans de nombreux cas, il rend le code plus lisible et est, entre autres, un élément d'un bon style de programmation.

Attributs de paramètres supplémentaires


Lors de la description des arguments de fonction ou des paramètres de script, leurs attributs supplémentaires peuvent être définis. L'exemple le plus simple est une installation forcée du type:

param([int]$arg0)

ou

function test ([int]$arg0) {
}

En plus de la conversion de type, vous pouvez utiliser l'attribut [parameter ()]:

param(
    [parameter(Argument1=value1, Argument2=value2)]
    $ParameterName
)

Avec son aide, il est facile de rendre le paramètre obligatoire. Faites attention à l'utilisation simultanée de plusieurs attributs - dans ce cas, ils se succèdent:

param([parameter(Mandatory=$true)][int]$arg0)

ou

function test ([parameter(Mandatory=$true)][int]$arg0) { 
}

ou

function test {
          parameter([parameter(Mandatory=$true)][int]$arg0)
}


image

La position permet de spécifier l'ordre du paramètre (par défaut, il correspond à l'ordre de la déclaration):

param(
                    [parameter(Mandatory=$true, Position=0)]
                    [int]
                    $arg0,

                    [parameter(Position=1)]
                    [string]
                    $arg1,

                    [parameter(Position=2)]
                    [array]
                    $arg2
)

L'attribut [Parameter ()] contient d'autres arguments, dont une liste complète est disponible sur le site Web de Microsoft. D'autres attributs y sont décrits, à l'aide desquels vous pouvez valider les valeurs transmises, les vérifier à l'aide d'expressions régulières, etc. En voici quelques-uns:

[Alias ​​()] définit un alias pour le paramètre:

param(
    [parameter(Mandatory=$true)]
    [alias("ARG","ArgumentName")]
    [string[]]
    $arg0
)

L'opérateur de conversion [chaîne []] signifie que la valeur du paramètre est un tableau de chaînes.

[AllowNull ()] autorise $ null comme paramètre obligatoire:

param(
    [parameter(Mandatory=$true)]
    [AllowNull()]
    [string]
    $arg0
)

[AllowEmptyString ()] autorise une chaîne vide comme paramètre requis:

param(
    [parameter(Mandatory=$true)]
    [AllowEmptyString()]
    [string]
    $arg0
)

[AllowEmptyCollection ()] autorise un tableau vide comme paramètre requis:

param(
    [parameter(Mandatory=$true)]
    [AllowEmptyCollection()]
    [string[]]
    $arg0
)

Validation de [ValidatePattern ()] à l' aide d'une expression régulière:

param(
    [parameter(Mandatory=$true)]
    [ValidatePattern("[0-9][0-9][0-9][0-9]")]
    [string[]]
    $arg0
)

[ValidateLength ()] vérifie la longueur d'un paramètre de chaîne:

param(
    [parameter(Mandatory=$true)]
    [ValidateLength(1,10)]
    [string]
    $arg0
)

Passer des paramètres dans le pipeline


Dans le premier article de la série, nous avons parlé de la possibilité de transférer des données vers des applets de commande via un pipeline. Dans PowerShell, les applets de commande et les fonctions renvoient des objets ou des tableaux d'objets (résultats des instructions) et les reçoivent également en entrée. Pour voir cela, nous préparons l'une des applets de commande à l'aide de Get-Help:

Get-Help Stop-Process -Parameter Name


image

Grâce au pipeline, vous pouvez accepter des valeurs de paramètre pour lesquelles les attributs correspondants sont définis (ByValue et / ou ByPropertyName). Dans le premier cas, le paramètre sera mis en correspondance avec un objet reçu via le pipeline, à condition que son type corresponde à celui attendu. Dans le deuxième paramètre, la valeur sera la propriété de l'objet entrant dont le nom correspond au nom ou à l'alias de ce paramètre. Pour définir les attributs, utilisez [parameter ()] avec les arguments booléens ValueFromPipeline et ValueFromPipelineByPropertyName, dont la valeur par défaut est $ false:

param(
    [parameter(Mandatory=$true,
    ValueFromPipeline=$true)]
    [string[]]
    $Name
)

ou

param(
    [parameter(Mandatory=$true,
    ValueFromPipelineByPropertyName=$true)]
    [string[]]
    $Name
)

ValueFromPipelineByPropertyName est généralement utilisé si nécessaire pour passer plusieurs paramètres afin qu'il n'y ait pas de confusion, et l'argument peut être utilisé simultanément avec ValueFromPipeline:

param(
    [parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [string[]]
    $Name
)

Write-Host $Name


image

Comme vous pouvez le voir, les scripts peuvent également recevoir des paramètres via le pipeline, mais néanmoins, l'application pratique des attributs décrits ci-dessus est plus probable pour les fonctions avancées , qui seront discutées ci-dessous.

Structure du corps de la fonction


Dans PowerShell, une fonction peut inclure trois blocs de code facultatifs entre crochets d'instruction - Begin, Process et End. Cela ressemble à ceci:

function test
{
   param()
   begin {}
   process {}
   end {}
}

Le bloc Begin est le premier à être exécuté une fois, et si les paramètres sont passés à la fonction via le pipeline, le code s'exécutera avant l'arrivée du premier objet pour le traitement. Dans ce cas, les variables $ _ et $ PSItem du bloc Begin ne contiendront pas de valeurs. Si la fonction est appelée à l'aide de paramètres spécifiés explicitement, ils seront disponibles dans le bloc Begin, car il n'est pas nécessaire d'attendre la réception d'objets du pipeline. Ensuite, le bloc Process est exécuté: si les paramètres sont passés par le pipeline, il sera lancé un par un pour chaque objet. Dans le cas de paramètres explicitement spécifiés, le bloc Process ne démarre qu'une seule fois. La fonction se termine en exécutant le bloc Fin une fois. Évidemment, l'utilisation de ces constructions n'est justifiée que si la fonction peut recevoir des objets du pipeline:

function test
{

    param(
        [Parameter(ValueFromPipeline)]
        [string[]]
        $Param1,

        [string]$Param2
    )

    begin
    {
        Write-Host " Begin"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }

    process {
        Write-Host " Process"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }

    end
    {
        Write-Host " End"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }
}

«un», «deux», «trois» | test -Param2 'quatre'

image

[CmdletBinding ()] Attribut et fonctions avancées


Pour créer des fonctions «avancées» (et des scripts à proprement parler), vous pouvez utiliser l' attribut [ CmdletBinding () ]. En particulier, il vous permet de définir des fonctions avancées avec les capacités des applets de commande binaires compilées dans Visual Studio, qui sont des classes de classes .NET Core. Puisque cet attribut est utilisé principalement dans les fonctions, nous nous arrêterons sur elles:

function <Name>
{
    [CmdletBinding(ConfirmImpact=<String>,
    DefaultParameterSetName=<String>,
    HelpURI=<URI>,
    SupportsPaging=<Boolean>,
    SupportsShouldProcess=<Boolean>,
    PositionalBinding=<Boolean>)]

    Param ()

    Begin{}
    Process{}
    End{}
}

En fait, [CmdletBinding ()] initialise une nouvelle instance de la classe CmdletBindingAttribute en appelant un constructeur auquel des arguments facultatifs peuvent être passés. Leur description détaillée se trouve sur le site Web de Microsoft. L'attribut CmdletBinding vous permet de contrôler des fonctionnalités supplémentaires de la fonction avancée: ajouter la prise en charge de -Confirm et -WhatIf (via SupportsShouldProcess), -Force, -Verbose et -Debug, ainsi que désactiver la liaison de paramètres positionnels, etc. Nous analyserons ensuite l'utilisation de paramètres spéciaux.

Le paramètre -Force est utilisé pour supprimer les demandes pour diverses opérations;

-Et qu'est-ce qui se passerait sinécessaire pour émuler le lancement et afficher des informations sur les conséquences de l'exécution d'une fonction (commande) sans ce paramètre. Couramment utilisé si une fonction peut effectuer des actions destructrices.

Remove-Item C: \ Windows \ notepad.exe -WhatIf

image

-Confirm nécessite une confirmation et est également utilisé si la fonction peut effectuer des actions destructrices.

function Delete-File {
[CmdletBinding(
    ConfirmImpact = 'High',
    SupportsShouldProcess = $true
)]
    param(
        [string]$File,
        [switch]$Force
    )
    if ($Force -or $PSCmdlet.ShouldProcess($File,"Delete file")) {
        Remove-Item $File
    }
}


image

Pour traiter -WhatIf et / ou -Confirm, la méthode ShouldProcess (SupportsShouldProcess = $ true) est appelée, ce qui invite ou émule l'exécution de la commande. Pour implémenter le traitement -Force, nous le mettons d'abord dans la condition IF. Tout d'abord, l'expression à gauche de l'opérateur -or est vérifiée, et si elle est vraie, le test s'arrête - la méthode ShouldProcess ne sera pas appelée. De plus, dans l'attribut [CmdletBinding ()], nous avons spécifié l'argument ConfirmImpact, qui détermine le niveau d'influence du code sur le système et inclut le gestionnaire de paramètres -Confirm. Cet argument peut prendre les valeurs suivantes:

Aucune ou non spécifiée - les messages de confirmation ne seront pas affichés, même si le paramètre -Confirm est passé.

Faible - la fonction affecte légèrement le système et ne crée pas de risques importants de perte de données.

Moyen - exposition moyenne avec peu de risque de perte de données à la suite d'actions destructrices.

Élevé - le code crée un risque élevé de perte de données suite à des actions destructrices.

Par défaut, pour une session PowerShell, le niveau d'exposition est considéré comme élevé. La valeur actuelle est stockée dans la variable $ ConfirmPreference, et si le code a le même ou un plus haut impact sur le système, une demande de confirmation sera toujours affichée.

Options -Verbose et -Debugnécessaire pour afficher les informations de débogage. Leur utilisation est considérée comme un bon style de programmation (oubliez Write-Host, ce n'est pas nécessaire dans les fonctions avancées). Le premier paramètre affiche des informations sur la progression et le second - des informations de débogage détaillées. Il permet également de passer à l'exécution de code étape par étape. Le comportement de -Verbose et -Debug est défini comme suit:

function Get-Something {
[CmdletBinding()]
    param()
    if ($PSBoundParameters.Verbose) {$VerbosePreference = "Continue"}
    if ($PSBoundParameters.Debug) {$DebugPreference = "Continue"}
    Write-Verbose "Type some verbose information"
    Write-Debug "Type some debug information"
}

Pour travailler avec des paramètres spéciaux, nous avons utilisé la variable $ PSBoundParameters. Par défaut, les valeurs de $ VerbosePreference et $ DebugPreference sont égales à 'SilentlyContinue', par conséquent, même si les paramètres correspondants sont spécifiés, les informations de débogage ne seront pas affichées - elles doivent être transférées à l'état 'Continue'.

Modules de script et création d'applet de commande


Commençons par créer nos propres applets de commande. En fait, ce sont des fonctions avancées qui sont décrites dans le soi-disant modules de script - fichiers texte avec l'extension .psm1. Ils sont stockés dans des répertoires définis dans la variable d'environnement PSModulePath. Vous pouvez afficher leurs chemins d'accès à l'aide de la commande suivante:

Get-ChildItem Env: \ PSModulePath | Format-Table -AutoSize

L'ensemble standard ressemble à ceci:

C: \ Users \% UserName% \ Documents \ WindowsPowerShell \ Modules
C: \ Program Files \ WindowsPowerShell \ Modules
C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ Modules

Après avoir créé le fichier ModuleName.psm1 avec la fonction Delete-File étendue de la section précédente, vous devez l'enregistrer, par exemple, dans] C: \ Users \% UserName% \ Documents \ WindowsPowerShell \ Modules \ ModuleName. Veuillez noter que le module de script doit être stocké dans un sous-répertoire séparé, dont le nom coïncide avec le nom de base (sans extension) du fichier .psm1. Après avoir exécuté la commande Import-Module ModuleName , la fonction Delete-File sera disponible pour l'utilisateur, et puisqu'elle est avancée, du point de vue pratique, il s'agit de la même applet de commande.

image

Dans cet article, nous avons examiné suffisamment en détail le passage des paramètres aux fonctions et aux scripts. La prochaine partie de la série se concentrera sur la programmation orientée objet.

Partie 1: Windows PowerShell Essentials
2: Windows PowerShell
4: ,



All Articles