Comment passer plusieurs paramètres dans une fonction de PowerShell?

si j'ai une fonction qui accepte plus d'un paramètre de chaîne, le premier paramètre semble recevoir toutes les données qui lui sont attribuées, et les paramètres restants sont passés comme vides.

Un test rapide de script:

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test("ABC", "DEF")

la sortie générée est

$arg1 value: ABC DEF
$arg2 value: 

la sortie correcte devrait être:

$arg1 value: ABC
$arg2 value: DEF

Cela semble être cohérent entre v1 et v2 sur plusieurs machines, donc évidemment, je suis en train de faire quelque chose de mal. Quelqu'un peut-il point exactement ce à quoi?

328
demandé sur George Stocker 2011-02-14 04:59:53

14 réponses

Les paramètres

dans les appels à des fonctions dans PowerShell (toutes les versions) sont séparés par des espaces, pas par des virgules. De plus, les parenthèses sont totalement inutiles et causeront une erreur d'analyse dans PowerShell 2.0 (ou plus tard) si Set-StrictMode est actif. Les arguments entre parenthèses ne sont utilisés que dans les méthodes .NET.

function foo($a, $b, $c) {
   "a: $a; b: $b; c: $c"
}

ps> foo 1 2 3
a: 1; b: 2; c: 3
451
répondu x0n 2018-08-21 14:25:58

la bonne réponse a déjà été fournie, mais cette question semble assez répandue pour justifier quelques détails supplémentaires pour ceux qui veulent comprendre les subtilités. J'aurais ajouté ceci juste comme un commentaire mais je voulais inclure une illustration--je l'ai déchiré de mon tableau de référence rapide sur les fonctions de PowerShell. Cela suppose que la signature de f est f($a, $b, $c) :

syntax pitfalls of a function call

ainsi, on peut appeler une fonction avec paramètres de position ou paramètres indépendants de l'ordre nommés . Les autres pièges révèlent que vous devez être conscient de virgules, parenthèses, et espace blanc.

pour lire l'article Down the Rabbit Hole: A Study in PowerShell Pipelines, Functions, and Parameters vient de paraître Simple-Talk.com. L'article contient un lien vers le quick référence/mur graphique.

215
répondu Michael Sorens 2013-04-08 15:26:41

vous appelez des fonctions PowerShell sans la parenthèse et sans utiliser la virgule comme un séparateur. Essayez d'utiliser:

   test "ABC" "DEF"

dans PowerShell la virgule (,) est un opérateur de réseau, p.ex.

   $a = "one", "two", "three"

définit $a à un tableau avec trois valeurs.

38
répondu Todd 2016-09-05 14:28:46

quelques bonnes réponses ici, mais je voulais souligner quelques autres choses. Les paramètres de fonction sont en fait un endroit où PowerShell brille. Par exemple, vous pouvez avoir des paramètres nommés ou positionnels dans des fonctions avancées comme so:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [int] $Id
    )
}

alors vous pouvez soit l'appeler en spécifiant le nom du paramètre, soit utiliser simplement les paramètres de position, puisque vous les avez définis explicitement. Ainsi, l'une ou l'autre de ces solutions fonctionnerait:

Get-Something -Id 34 -Name "Blah" 
Get-Something "Blah" 34

le premier exemple fonctionne même si le nom est fourni en second, parce que nous avons explicitement utilisé le nom du paramètre. Le deuxième exemple fonctionne cependant sur la base de la position, ainsi le nom devrait être le premier. Lorsque c'est possible, j'essaie toujours de définir les positions afin que les deux options soient disponibles.

PowerShell a également la capacité de définir des ensembles de paramètres. Il utilise cette méthode au lieu de la surcharge de la méthode, et encore une fois est très utile:

function Get-Something
{
    [CmdletBinding(DefaultParameterSetName='Name')]
    Param
    (
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Name')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Id')]
         [int] $Id
    )
}

maintenant le la fonction sera de prendre un nom ou un identifiant, mais pas les deux. Vous pouvez les utiliser positionnellement, ou par leur nom. Comme ils sont d'un type différent, PowerShell va le découvrir. Donc tout cela fonctionnerait

Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23

vous pouvez également assigner des paramètres supplémentaires aux différents ensembles de paramètres. (C'était un exemple assez basique évidemment) à l'intérieur de la fonction, vous pouvez déterminer quel paramètre a été utilisé avec $PsCmdlet.Propriété ParameterSetName. Par exemple:

if($PsCmdlet.ParameterSetName -eq "Name")
{
    Write-Host "Doing something with name here"
}

ensuite, sur une note connexe, il y a aussi la validation des paramètres dans PowerShell. C'est l'une de mes fonctionnalités préférées de PowerShell, et cela rend le code à l'intérieur de vos fonctions très propre. Il y a de nombreuses validations que vous pouvez utiliser. Quelques exemples sont

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidatePattern('^Some.*')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [ValidateRange(10,100)]
         [int] $Id
    )
}

dans le premier exemple, ValidatePattern accepte une expression régulière qui assure que le paramètre fourni correspond à ce que vous attendez. Si ce n'est pas le cas, une exception intuitive est jeté, vous disant exactement ce qui ne va pas. Dans cet exemple, "quelque chose" fonctionnerait bien, mais "Summer" ne réussirait pas la validation.

ValidateRange garantit que la valeur du paramètre se situe entre les valeurs que vous attendez pour un entier. Donc 10 ou 99 fonctionneraient, mais la 101 ferait une exception.

un est ValidateSet, qui vous permet de définir explicitement un tableau de valeurs acceptables. Si quelque chose d'autre est entré, une exception sera levée. Il y en a d'autres aussi, mais probablement le plus utile un est ValidateScript. Cela prend un bloc de script qui doit évaluer à $ true, donc le ciel est la limite. Par exemple:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
         [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
         [string] $Path
    )
}

dans cet exemple, nous sommes assurés non seulement que $Path existe, mais qu'il s'agit d'un fichier (par opposition à un répertoire) et qu'il a un .csv extension. ($_se réfère au paramètre, lorsque vous êtes dans votre scriptblock.) Vous pouvez également passer dans beaucoup plus grand, des blocs de script multi-lignes si ce niveau est requis, ou utilisez plusieurs scriptblocks comme je l'ai fait ici. C'est extrêmement utile, et permet de belles fonctions propres et des exceptions intuitives.

19
répondu user2233949 2017-10-31 16:11:26
Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test "ABC" "DEF"
13
répondu John B 2011-11-04 20:31:00

si vous êtes un développeur C# / Java / C++ / Ruby / Python / Pick-A-Language-From-This-Century et que vous voulez appeler votre fonction avec des virgules, parce que c'est ce que vous avez toujours fait, alors vous avez besoin de quelque chose comme ceci:

$myModule = new-module -ascustomobject { 
    function test($arg1, $arg2) { 
        echo "arg1 = $arg1, and arg2 = $arg2"
    }
}

maintenant appelez:

$myModule.test("ABC", "DEF")

et vous verrez

arg1 = ABC, and arg2 = DEF
10
répondu Ryan Shillington 2017-02-20 14:54:20

si vous essayez:

PS > Test("ABC", "GHI") ("DEF")

, vous obtenez:

$arg1 value: ABC GHI
$arg2 value: DEF

donc vous voyez que la parenthèse sépare les paramètres

si vous essayez:

PS > $var = "C"
PS > Test ("AB" + $var) "DEF"

, vous obtenez:

$arg1 value: ABC
$arg2 value: DEF

Maintenant vous pouvez trouver une utilité immédiate de la parenthèse - un espace ne deviendra pas un séparateur pour le prochain paramètre - à la place vous avez une fonction eval.

5
répondu RaSor 2017-02-20 15:01:57

si vous ne savez pas (ou vous en souciez) combien d'arguments vous passerez à la fonction, vous pouvez aussi utiliser une approche très simple comme;

Code :

function FunctionName()
{
    Write-Host $args
}

qui imprimerait tous les arguments. Par exemple:

FunctionName a b c 1 2 3

Sortie

a b c 1 2 3

je trouve cela particulièrement utile lors de la création de fonctions qui utilisent des commandes externes cela pourrait avoir beaucoup de paramètres différents (et optionnels), mais s'appuie sur ladite commande pour fournir une rétroaction sur les erreurs de syntaxe etc.

voici un autre exemple du monde réel (créer une fonction à la commande tracert, que je déteste devoir se souvenir du nom tronqué);

Code :

Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}
4
répondu Draino 2017-01-27 02:49:20

Je ne sais pas ce que vous faites avec la fonction, mais regardez en utilisant le mot-clé 'param'. Il est un peu plus puissant pour passer des paramètres à une fonction, et le rend plus convivial. Ci-dessous est un lien vers un article trop complexe de Microsoft à ce sujet. Il n'est pas aussi compliqué que l'article indique son. Usage Param

aussi, voici un exemple d'un thread sur ce site:

regardez ça.

3
répondu Rodney Fisk 2017-05-23 12:26:36
Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test("ABC") ("DEF")
2
répondu kleopatra 2014-01-22 09:06:35

je déclare plus tôt:

le problème courant est d'utiliser le singulier $arg , ce qui est incorrect.

Il doit toujours être au pluriel comme $args .

Le problème n'est pas que.

En fait, $arg peut être n'importe quoi d'autre. Le problème est l'utilisation de la virgule et la parenthèse.

J'exécute le code suivant qui a fonctionné et la sortie suit:

Code:

Function Test([string]$var1, [string]$var2)
{
    Write-Host "`$var1 value: $var1"
    Write-Host "`$var2 value: $var2"
}

Test "ABC" " DEF "

sortie:

$var1 valeur: ABC $ var2 valeur: DEF

1
répondu Eric 2013-11-08 00:44:06
Function Test {
 Param([string]$arg1, [string]$arg2)
    Write-Host $arg1
    Write-Host $arg2
}

ceci est une déclaration param en bonne et due forme https://technet.microsoft.com/en-us/library/dd347600.aspx

Et il fonctionne vraiment

1
répondu Sergii Kimlik 2017-05-17 13:00:09

parce qu'il s'agit d'une question fréquemment abordée, je tiens à mentionner qu'une fonction PowerShell devrait utiliser verbes approuvés ( verbe-nom comme nom de fonction). Vous pouvez également spécifier des choses comme si le paramètre est obligatoire et la position du paramètre:

function Test-Script
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$arg1,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$arg2
    )

    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Pour passer le paramètre à la fonction, vous pouvez soit utiliser la position :

Test-Script "Hello" "World"

Ou de vous spécifier le paramètre nom :

Test-Script -arg1 "Hello" -arg2 "World"

Vous ne pas utiliser les parenthèses comme vous le faites lorsque vous appelez une fonction en C#.


je recommande à toujours passer les noms de paramètre lorsque vous utilisez plus d'un paramètre, puisque c'est plus readible .

1
répondu Martin Brandl 2018-09-21 18:50:50

, Vous pouvez passer paramètres dans fonction comme cela aussi.

function FunctionName()
{
    Param ([string]$ParamName);
    #Operations
}
0
répondu Kaushal Khamar 2016-05-14 06:55:22