Question [Astuce]Analyse des paramètres d'un script/fnction

Plus d'informations
il y a 17 ans 6 mois #2753 par Laurent Dardenne
Le code suivant est spécifique à b]PowerShell v2 CTP2[/b. Voir les posts suivant pour une solution en PowerShell v1.

Une petite astuce concernant l'analyse des paramètres d'un script ou d'une fonction.
Si on souhaite coder une analyse rigoureuse des paramètres de la ligne de commande, notamment savoir si un paramètre est mal orthographié ou inconnu, l'objet contextuel $MyInvocation peut nous être utile :
Fonction sans contrôle particulier :
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[switch] $Stop)
#Suite du traitement...
}

Test-UnBoundArguments
Test-UnBoundArguments \"Test\"
Test-UnBoundArguments -name \"Test\"
Test-UnBoundArguments -ParamInconnu 10
Test-UnBoundArguments -nime \"Test\"
Test-UnBoundArguments -Stop
Test-UnBoundArguments -SwitchInconnu
[/code:1]
Fonction contrôlant les paramètres inconnu, i.e. \"non lié\" (unbounded):
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[switch] $Stop)

if (($MyInvocation.UnBoundArguments).count -ne 0)
{Throw \"Le ou les paramètres suivants sont inconnus : $($MyInvocation.UnBoundArguments).\"}
#Suite du traitement ...
}

Test-UnBoundArguments
Test-UnBoundArguments \"Test\"
Test-UnBoundArguments -name \"Test\"
Test-UnBoundArguments -ParamInconnu 10
Test-UnBoundArguments -nime \"Test\"
Test-UnBoundArguments -Stop
Test-UnBoundArguments -SwitchInconnu
[/code:1]
La même en récupèrant l'objet contextuel $MyInvocation
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[switch] $Stop)

if (($MyInvocation.UnBoundArguments).count -ne 0)
{ #récupére l'objet via le pipe
$MyInvocation}
}

$I=Test-UnBoundArguments -ParamInconnu 10
$I1=Test-UnBoundArguments -nime \"Test\" -name \"Test\"
$I2=Test-UnBoundArguments -Stop
$I3=Test-UnBoundArguments -SwitchInconnu -Stop
$I
$I1
#Aucune infos car aucune erreur de détectée
$I2
$I3
$I4
[/code:1]
Un autre problème, les paramètres de type contraint sont initialisés à une valeur par défaut, par exemple pour les entiers à zéro, on ne peut donc pas les tester sur la valeur $null afin de déterminer si un paramètre est présent ou non sur la ligne de commande.
Et dans certains cas la valeur attribuée par défaut peut ne pas être souhaitable.
Mais alors on peut tester $MyInvocation.CommandLineParameters :
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[int]$Nombre,[switch] $Stop)

if (($MyInvocation.UnBoundArguments).count -ne 0)
{Throw \"Le ou les paramètres suivants sont inconnus : $($MyInvocation.UnBoundArguments).\"}

if (($MyInvocation.CommandLineParameters.Nombre -eq $null))
{Write-Warning \"Le paramètre Nombre n'est pas précisé.\"}
\"Nombre =$Nombre\"
}

Test-UnBoundArguments -nombre 5
Test-UnBoundArguments -nombre
Test-UnBoundArguments
[/code:1]
On déclare une valeur par défaut pour le paramètre $Nombre :
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[int]$Nombre=3,[switch] $Stop)

if (($MyInvocation.UnBoundArguments).count -ne 0)
{Throw \"Le ou les paramètres suivants sont inconnus : $($MyInvocation.UnBoundArguments).\"}

if (($MyInvocation.CommandLineParameters.Nombre -eq $null))
{Write-Warning \"Le paramètre Nombre n'est pas précisé mais prend la valeur par défaut.\"}
\"Nombre =$Nombre\"
}

Test-UnBoundArguments -nombre 5
Test-UnBoundArguments -nombre
Test-UnBoundArguments
[/code:1]
Dans ce cas bien évidemment la valeur attribuée par défaut est bien celle attendue et ne pose pas de pb.<br><br>Message édité par: Laurent Dardenne, à: 12/10/08 19:31

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 6 mois #2756 par Arnaud Petitjean
Excellent article Laurent ! :woohoo:

Je suis en ce moment en train de jouer avec la dernière build de PowerShell (pas encore officielle) et je peux te dire qu'il y a beaucoup de changements super intéressants du côté de l'analyse des paramètres.

On peut par exemple définir des paramètres comme obligatoires, vérifier l'ordre dans lequel les paramètres sont passés, s'assurer de la validité des valeurs des paramètres, ainsi que beaucoup beaucoup d'autres possibilités. Je ne peux pas en dire plus pour le moment, mais je sais que j'en ai déjà trop dit... Chutt !!! :whistle:

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 6 mois #2757 par Laurent Dardenne
Arnaud écrit:

Je ne peux pas en dire plus pour le moment, mais je sais que j'en ai déjà trop dit... Chutt !!!

N'est-ce pas la syntaxe des script-cmdlet déjà énoncé dans la CTP2,comme dans cet exemple :
get-powershell.com/2008/06/14/building-s...-cmdlets-as-objects/
?

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 6 mois #2760 par Arnaud Petitjean
Oui l'idée est là mais dans la CTP que j'ai entre les mains l'accès aux spécifications des paramètres a été nettement simplifié. De même que l'on spécifier beaucoup plus de contraintes.

Je pense que la CTP3 est programmée pour la TechEd de Barcelone le mois prochain.

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 6 mois #2762 par Laurent Dardenne
Arnaud écrit:

Je pense que la CTP3 est programmée pour la TechEd de Barcelone le mois prochain.

Penses-tu qu'elle sera publique par la suite ?
Et coté documentation c'est tjr aussi succint ?

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 5 mois #2941 par Laurent Dardenne
Pour PowerShell V1 on peut utiliser la fonction suivante. En revanche les paramètres à tester ne doivent plus être contraint sur le type.
[code:1]
function ValidateParameter([string]$Name,$Parameter,[Type] $Type)
{ # Renvoi True si le type est celui attendu et si le contenu n'est pas $Null ou si on peut caster
# la valeur reçue dans le type attendu
# Renvoi False si le contenu est à $Null.
# Déclenche une exception ArgumentTransformationMetadataException si le type n'est pas celui attendu.

Write-Debug \&quot;ValidateParameter\&quot;
Write-debug \&quot;$Name\&quot;
if ($Parameter -ne $null)
{Write-debug \&quot;$($Parameter.GetType())\&quot;}
else {Write-debug \&quot;`$Parameter est à `$null.\&quot;}
Write-debug \&quot;$Parameter\&quot;
Write-debug \&quot;$Type\&quot;


if (($Parameter -eq $null))
{ Write-Debug \&quot;Le paramètre $Name est à `$null.\&quot;
return $False
}
elseif ($Parameter -isNot $Type)
{ #Peut-on caster la valeur reçue dans le type attendu ?
if (!($Parameter -as $Type))
{
#récupére le contexte d'appel de l'appelant
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
throw (new-object System.Management.Automation.ArgumentTransformationMetadataException \&quot;$($Invocation.MyCommand).$($MyInvocation.MyCommand) : Impossible de convertir la valeur « $Parameter » en type « $($Type.ToString()) ».\&quot;«»)
}
}
return $True
} #ValidateParameter
[/code:1]
Un exemple d'appel
[code:1]
if ( (!(ValidateParameter \&quot;Increment_By\&quot; $Increment_By System.Int32) ) -and ($Increment_By -eq 0) )
{Throw \&quot;La valeur de Increment_By doit être un entier différent de zéro.\&quot;}
[/code:1]
ou encore
[code:1]
if ( ($Signe -eq 1) -and
#test si les paramètres sont à $null
(!(ValidateParameter \&quot;Start_With\&quot; $Start_With System.Int32)) -and
(!(ValidateParameter \&quot;MaxValue\&quot; $MaxValue System.Int32)) -and
(!(ValidateParameter \&quot;MinValue\&quot; $MinValue System.Int32))
)
{ write-Debug \&quot;`tSéquence ascendante. Valeur par défaut.\&quot;
$Start_With=1
$MaxValue=[int]::MaxValue
$MinValue=1
}
[/code:1]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.098 secondes
Propulsé par Kunena