Question
Utilisation d'arguments optionnels dans un script
- Bruno Travouillon
- Auteur du sujet
- Hors Ligne
- Nouveau membre
- Messages : 10
- Remerciements reçus 0
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.
- Laurent Dardenne
- Hors Ligne
- Modérateur
- Messages : 6302
- Remerciements reçus 68
brunot écrit:
Je ne pense pas, il faudrait vérifier ce comportement avec la v1.Je suis certainement passé à côté de certaines subtilités du langage.
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:
Ce n'est pas évident à expliquer puisque là on touche au parseur de la ligne de commande.Si quelqu'un est capable de m'expliquer pourquoi j'obtiens ce mode de fonctionnement, je serais ravi qu'il m'explique
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
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
ps
En même tempps, je ne suis pas certains d'avoir répondu à ta question <br><br>Message édité par: Laurent Dardenne, à: 22/02/10 21:08
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Bruno Travouillon
- Auteur du sujet
- Hors Ligne
- Nouveau membre
- Messages : 10
- Remerciements reçus 0
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 = \"foo\", [int]$n = 42)
echo $firstname
echo $lastname
echo $foo
echo $n
foreach ($arg in $args) {
echo \"Argument : $arg\"
}
[/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 ) 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.
- Laurent Dardenne
- Hors Ligne
- Modérateur
- Messages : 6302
- Remerciements reçus 68
brunot écrit:
Lequel est-il ?J'arrive (presque) à obtenir le comportement souhaité.
brunot écrit:
La première fonctionne, car dans une fonction avancée, -V référence le paramètre Verbose.Les combinaisons suivantes ne fonctionnent plus :
./castest.ps1 -v JOHN DOE
Utilise $PSBoundParameters pour le visualiser.
brunot écrit:
Voir + haut, on ne sait pas ce que tu veux faire, ni le comportement attendu.J'ai l'impression que forcer le positionnement des paramètres empêche l'utilisation des switch...
brunot écrit:
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.On peut quand même regretter l'absence d'une fonction getopts
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:
Merci.Au passage, merci pour tes publications de qualité (c'est rare) et pour WinMerge
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Bruno Travouillon
- Auteur du sujet
- Hors Ligne
- Nouveau membre
- Messages : 10
- Remerciements reçus 0
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 = \"foo\", [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.
- Laurent Dardenne
- Hors Ligne
- Modérateur
- Messages : 6302
- Remerciements reçus 68
brunot écrit:
En v2 le paramètre -? a été ajouté ce qui évite de faire appel à Get-Help nomFonction :Le comportement attendu est de pouvoir afficher l'aide avec l'utilisation du switch -h, sans autre argument.
[code:1]
Test-ContainsWildcardCharacters -?
[/code:1]
brunot écrit:
Non, comme indiqué dans le document cité.Concernant le switch -v qui devient Verbose, est-ce le seul ?
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(\"_\"«»).Value
Write-Debug \"Caller = $S\"
If ([Management.Automation.WildcardPattern]::ContainsWildcardCharacters($InputObject))
{ throw (new-object VMException ($MessageTable.EVAGlobbing -F $InputObject)) }
$true
<#
.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 :
\"Le globbing (?,*,[]) n'est pas supporté (path).\"
.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
#>
} #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:
Peut être dans ce doc , mais je n'en suis pas certains.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)
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.
- Vous êtes ici :
- Accueil
- forum
- PowerShell
- Entraide pour les débutants
- Utilisation d'arguments optionnels dans un script