Question Utilisation d'arguments optionnels dans un script

Plus d'informations
il y a 14 ans 2 mois #6228 par Bruno Travouillon
Bonjour,

Je rencontre un problème lorsque je tente d'utiliser des arguments dans un script.

Fonctionnement souhaité de la commande :
./castest.ps1 [OPTIONS] PRENOM NOM

.Exemple de code castest.ps1
[code:1]
param([string]$foo = \"$foo\", [int]$n = 42)
echo $foo
echo $n

foreach( $arg in $args ) {
echo \"Argument : $arg\"
}
[/code:1]

Sans paramètres, c'est le résultat attendu :

./castest.ps1
foo
42


Avec les paramètres, c'est également le résultat attendu

./castest.ps1 -foo bar -n 1
bar
1


J'y rajoute des arguments, c'est toujours bon

./castest.ps1 -foo bar -n 1 JOHN DOE
bar
1
Argument : JOHN
Argument : DOE


Les arguments -foo et -n sont optionnels (et définis respectivement à foo et 42 par défaut)

./castest.ps1 JOHN DOE
.\castest.ps1 : Impossible de traiter la transformation d'argument sur le paramètre « n ». Impossible de convertir la valeur « DOE » en type « System.Int32 ». Erreur : « Input string was not in a correct format. »
Au niveau de ligne : 1 Caractère : 11
+ ./test.ps1 <<<< JOHN DOE
+ CategoryInfo : InvalidData: (: ) [castest.ps1], ParameterBindin...m
ationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,castest.ps1


Étant donné qu'il tente de convertir « DOE » en entier, qu'est devenu « JOHN » :

./castest.ps1 JOHN
JOHN
42


Par contre ça fonctionne en remplaçant la valeur de « JOHN » par « -JOHN »

./castest.ps1 -foo bar -JOHN DOE
bar
42
Argument : -JOHN
Argument : DOE


Je suis certainement passé à côté de certaines subtilités du langage. Si quelqu'un est capable de m'expliquer pourquoi j'obtiens ce mode de fonctionnement, je serais ravi qu'il m'explique :)

J'utilise PowerShell V2 sur Windows XP SP3 32 bits.

++

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

Plus d'informations
il y a 14 ans 2 mois #6230 par Laurent Dardenne
Salut,
brunot écrit:

Je suis certainement passé à côté de certaines subtilités du langage.

Je ne pense pas, il faudrait vérifier ce comportement avec la v1.
Ce n'est pas du domaine du langage mais de l'analyse de la ligne de commande, suivi de la liaison des arguments de chaque paramètre.
brunot écrit:

Si quelqu'un est capable de m'expliquer pourquoi j'obtiens ce mode de fonctionnement, je serais ravi qu'il m'explique :)

Ce n'est pas évident à expliquer puisque là on touche au parseur de la ligne de commande.
On peut déjà tracer la liaison des paramètres :

[code:1] #erreur
Trace-Command -name ParameterBinding {.\test2.ps1 -foo bar JOHN DOE} –file c:\temp\trace1.txt
#PAS d'erreur
Trace-Command -name ParameterBinding {.\test2.ps1 -foo bar -JOHN DOE} –file c:\temp\trace2.txt[/code:1]En utilisant WinMerge (cf. sourceforge) sur les 2 fichiers trace, on peut supposer que PS v2 interpréte la présence du tiret sur JOHN comme un paramètre et non pas comme un argument \"restant\" (REMAININGARGUMENTS).
Ce qui fait que PS lie la valeur par défaut de $n.

Si on utilise la syntaxe des fonctions avancées ,
[code:1]
[cmdletBinding()]
param([string]$foo = \"foo\", [int]$n = 42)
...
[/code:1]
le comportement différe :
[code:1]
PS C:\temp> .\test2.ps1 -foo bar -JOHN DOE
C:\temp\test2.ps1 : Impossible de trouver un paramètre correspondant au nom « JOHN ».
Au niveau de ligne : 1 Caractère : 27
+ .\test2.ps1 -foo bar -JOHN <<<< DOE
+ CategoryInfo : InvalidArgument: (:«») [test2.ps1], ParameterBindingException
...
[/code:1]
Ce qui est normal puisque c'est le rôle de l'attribut cmdletBinding, en revanche on peut supposer que le code d'analyse est identique. La présence de l'attribut \"contraignant\" la liaison.
Mais là seul MS peut dire s'il s'agit d'un bug ou du comportement attendu, car eux ont la doc :P

Voir aussi :
[code:1]
#identique avec ou sans l'attribut cmdletBinding
.\test2.ps1 -foo bar -\"\" DOE
#C:\temp\test2.ps1 : Impossible de traiter la transformation d'argument sur le paramètre « n ». Impossible de convertir la valeur « - » en type « System.Int32 ».
#Erreur : « Le format de la chaîne d'entrée est incorrect. »
[/code:1]
PowerShell c'est facile :blink:

ps
En même tempps, je ne suis pas certains d'avoir répondu à ta question :lol:<br><br>Message édité par: Laurent Dardenne, à: 22/02/10 21:08

Tutoriels PowerShell

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

Plus d'informations
il y a 14 ans 2 mois #6232 par Bruno Travouillon
Bonsoir,

Merci pour ta réponse et ton lien qui m'ont mis sur la voie.

J'arrive (presque) à obtenir le comportement souhaité.

[code:1]
param([parameter(position=0)][string]$firstname, [parameter(position=1)][string]$lastname, [string]$foo = \&quot;foo\&quot;, [int]$n = 42)
echo $firstname
echo $lastname
echo $foo
echo $n

foreach ($arg in $args) {
echo \&quot;Argument : $arg\&quot;
}
[/code:1]

Les combinaisons suivantes fonctionnent :

./castest.ps1 JOHN DOE
./castest.ps1 -foo bar -n 2 JOHN DOE
./castest.ps1 JOHN DOE -foo bar -n 2
./castest.ps1 -foo bar JOHN DOE -n 2
./castest.ps1 -foo bar JOHN DOE


Les combinaisons suivantes ne fonctionnent plus :

./castest.ps1 -v JOHN DOE
# $args n'est pas defini
./castest.ps1 -h
# Impossible de trouver un paramètre correspondant au nom « h »


J'ai l'impression que forcer le positionnement des paramètres empêche l'utilisation des switch...

On peut quand même regretter l'absence d'une fonction getopts(). PowerShell simplifie l'écriture de script par rapport à WSH (ne parlons pas de DOS :whistle: ) mais ça devient vite compliqué pour utiliser des composants essentiels tels que les paramètres de scripts.

Au passage, merci pour tes publications de qualité (c'est rare) et pour WinMerge :)

++

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

Plus d'informations
il y a 14 ans 2 mois #6241 par Laurent Dardenne
Salut,
brunot écrit:

J'arrive (presque) à obtenir le comportement souhaité.

Lequel est-il ?
brunot écrit:

Les combinaisons suivantes ne fonctionnent plus :

./castest.ps1 -v JOHN DOE

La première fonctionne, car dans une fonction avancée, -V référence le paramètre Verbose.
Utilise $PSBoundParameters pour le visualiser.
brunot écrit:

J'ai l'impression que forcer le positionnement des paramètres empêche l'utilisation des switch...

Voir + haut, on ne sait pas ce que tu veux faire, ni le comportement attendu.
brunot écrit:

On peut quand même regretter l'absence d'une fonction getopts

De mon coté je n'en ai pas ressenti le besoin, mais c'est vrai que la v1 nécessitait de contrôler les paramètres si on voulait bétonner leur gestion.
Pour la v2 il faut peut être un temps d'adaptation et accepter d'être déchargé de certains traitements en ayant qq contraintes.
Rien n'empêche de tout recoder, voir de coupler du C#, ou autre, si besoin.
brunot écrit:

Au passage, merci pour tes publications de qualité (c'est rare) et pour WinMerge :)

Merci.

Tutoriels PowerShell

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

Plus d'informations
il y a 14 ans 1 mois #6266 par Bruno Travouillon
Bonsoir,

Le comportement attendu est de pouvoir afficher l'aide avec l'utilisation du switch -h, sans autre argument.

En prenant le temps de lire calmement ton document, j'y apprends qu'il est possible de déclarer un type [switch] dans param().

Ainsi, la déclaration suivante fonctionne très bien :

[code:1]param([parameter(position=0)][string]$firstname, [parameter(position=1)][string]$lastname, [string]$foo = \&quot;foo\&quot;, [int]$n = 42, [switch]$h)[/code:1]

Concernant le switch -v qui devient Verbose, est-ce le seul ?
Existe-t'il un document expliquant les bases de l'écriture de scripts sous PowerShell ? (gestion des arguments, inclusion de fonctions depuis un paquet, etc)

Merci

++

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

Plus d'informations
il y a 14 ans 1 mois #6270 par Laurent Dardenne
Salut,
brunot écrit:

Le comportement attendu est de pouvoir afficher l'aide avec l'utilisation du switch -h, sans autre argument.

En v2 le paramètre -? a été ajouté ce qui évite de faire appel à Get-Help nomFonction :
[code:1]
Test-ContainsWildcardCharacters -?
[/code:1]
brunot écrit:

Concernant le switch -v qui devient Verbose, est-ce le seul ?

Non, comme indiqué dans le document cité.
Pour la fonction avancée suivante (code incomplet) :
[code:1]
Function Test-ContainsWildcardCharacters{
[CmdletBinding()]
param ($InputObject)
Write-Debug ($FrmtCall -F $MyInvocation.InvocationName)

$s=$PSCmdlet.SessionState.PSVariable.Get(\&quot;_\&quot;«»).Value
Write-Debug \&quot;Caller = $S\&quot;
If ([Management.Automation.WildcardPattern]::ContainsWildcardCharacters($InputObject))
{ throw (new-object VMException ($MessageTable.EVAGlobbing -F $InputObject)) }
$true

&lt;#
.SYNOPSIS
Régle de validation d'arguments, recherche si le path contient des caractères jokers : ?,*,[].

.DESCRIPTION
Un traitement peut ne pas vouloir accepter le globbing pour un path. Si la valeur de l'argument contient
des caractères jokers, l'exception suivante est déclenchée :
\&quot;Le globbing (?,*,[]) n'est pas supporté (path).\&quot;

.PARAMETER InputObject
Contient la valeur à valider.

.EXAMPLE
todo code...

Description
todo

.INPUTS
Une chaîne contenant le nom de chemin à valider.

.OUTPUTS
Une valeur booléenne, true indiquant que la validation a réussie.

.FUNCTIONALITY
ValidationArgument

.COMPONENT
PowerShell

.ROLE
SoftwareDeveloper

.LINK
msdn.microsoft.com/en-us/library/aa717088(VS.85).aspx
#&gt;
} #Test-ContainsWildcardCharacters
[/code:1]
On peut recupérer la liste de ses paramètres ainsi :
[code:1]
$F=gcm Test-ContainsWildcardCharacters
$F.parameters
[/code:1]
Ensuite la liste dépend de l'usage de l'attribut CmdletBinding et de son paramètrage.

brunot écrit:

Existe-t'il un document expliquant les bases de l'écriture de scripts sous PowerShell ?
(gestion des arguments, inclusion de fonctions depuis un paquet, etc)

Peut être dans ce doc , mais je n'en suis pas certains.
Si tu codes en V2 utilise les modules, bien que pour le moment ce ne soit est pas vraiment documenté.

Si tu veux, tu peux ouvrir un post concernant les bases de l'écriture de scripts et y poster toutes tes questions, cela pourra par la suite servir à la rédaction d'un tuto sur le sujet.

Tu peux aussi consulter le code du projet Add-Lib .

Tutoriels PowerShell

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

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