Introduction
Dans cet article je vais partager avec vous des méthodes que j’utilise afin de travailler avec des noms de variable dynamiques.
On parle bien ici du nom de la variable et non de son contenu.
Car travailler avec du contenu dynamique n’a rien d’extraordinaire, c’est ce que font nos scripts en règle générale.
En revanche générer un nom de variable à “la volée” pour ensuite le réutiliser, ce n’est pas forcément si évident que cela.
Au premier abord on pourrait être tenté par des choses du genre :
PS C:\> $i = 1
PS C:\> Mavar$i = "test"
PS C:\> Mavar$i
# Ce qui renvoi l'erreur suivante :
# Mavar$i : Le terme « Mavar$i » n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou programme exécutable.
Ou
PS C:\> $(Mavar$i) = "test"
PS C:\> Mavar$i
# Ce qui renvoi l'erreur suivante :
# Au caractère Ligne:2 : 1
# + $(Mavar$i) = "test"
# + ~~~~~~~~~~
# L’expression d’affectation n’est pas valide.
Ou on rajoute des “ ‘ car on est sait qu’une chaine de caractère se met entre quote..
PS C:\> $("Mavar"$i) = "test"
PS C:\> Mavar$i
# Mais le résultat est le même, une erreur :
# Au caractère Ligne:2 : 10
# + $("Mavar"$i) = "test"
# + ~~
# Jeton inattendu « $i » dans l’expression ou l’instruction.
Bon je vais arrêter là pour les exemples qui ne fonctionnent pas… Mais il y en a plein d’autres :stuck_out_tongue_winking_eye:
Deux environnements
Je vais distinguer 2 cas de figure pour cet article. Le premier cas est celui de l’utilisation des noms dynamiques dans un script et le deuxième sera l’utilisation de ces noms dans un GUI fait en powershell.
1. Dans un script
a. Définition des variables dynamiques
Il arrive parfois que l’on ait besoin de générer des noms de variables lors de l’exécution d’un script. Le recourt aux variables dynamiques arrive souvent lorsque l’on ne connait pas le nombre de variable que l’on aura à créer.
En powershell v1+, New-Variable
est la commande qui permet de créer une variable est de lui assigner un contenu
PS C:\> new-Variable -Name "MaVar" -Value "test"
PS C:\> $Mavar
test
Mais bon, personnellement je ne l’utilise jamais ainsi… Préférant un bon vieux :
PS C:\> $MaVar = "test"
PS C:\> $Mavar
test
En revanche cette commande a l’avantage de pouvoir utiliser d’autres variables pour créer le nom de notre variable.
Exemple : je dois créer 5 variables et leurs affecter du contenu venant d’un Array
$MyArray = @('pomme','poire','banane','cerise','orange')
for ($i=0; $i -lt $MyArray.Length; $i++)
{
New-Variable -Name "MaVar$i" -Value $MyArray[$i]
}
Ce qui nous donnera comme résultats :
PS C:\> $MaVar0
pomme
PS C:\> $MaVar1
poire
PS C:\> $MaVar2
banane
On voit bien ici que l’on a maintenant 5 variables avec des noms différent et une valeur propre à chacune.
b. récupération des variables dynamiques
Nous avons vu comment définir un nom de variable de façon dynamique, nous allons maintenant voir que l’on peut faire la même chose mais cette fois ci, pour la récupération.
En effet la commande Get-Variable
permet de récupérer le contenu d’une variable
# Pour l'exemple on définit une variable $MaVar2
PS C:\> $MaVar2 = 'banane'
# On suppose que nous sommes dans une boucle et que $i = 2
PS C:\> $i = 2
# Maintenant récupérons le contenu de la variable $MaVar2.
PS C:\> Get-Variable -Name "MaVar$i" -ValueOnly
banane
Voilà on a bien le contenu de la variable $MaVar2 tout en partant d’une chaine de caractère et d’une autre variable, nous sommes donc bien dans la récupération de la valeure d’une variable avec un nom dynamique.
2. Dans un GUI”
Dans un GUI, la définition est la même, on part toujours avec un New-Variable -Name "Mavar$i" -Value $i
, en revanche c’est au moment de l’utilisation qu’il y a une petite astuce.
Pour l’exemple on va prendre 3 Checkbox avec les noms suivant ;
$CheckboxPomme
$CheckboxPoire
$CheckboxBanane
Imaginons une requete qui nous indique quel fruit on va manger aujourdhui :smiley:(oui je sais il en faut 5). On aura donc par exemple : Poire.
Mais comment cocher la bonne checkbox ?
Afin de faire ce que nous voulons, on va procéder ainsi :
#notre information d'entrée
$i = Poire #Information obtenu avec notre requete imaginaire
(Get-Variable -name "Checkbox{0}" -f $i)).value.Checked = $true
Voilà avec notre Get-Variable
de l’exemple ci-dessus, on a coché la checkbox $CheckboxPoire
.
L’astuce dont je parlais en début concerne le fait de passer par la value
de la checkbox et non pas directement par le checked, comme on le ferait avec le nom complet de la checkbox.
#Avec le nom complet de la checkbox
$Checkbox2.Checked = $true
#Avec un nom à construire dynamiquement
(Get-Variable -name "Checkbox{0}" -f $i)).value.Checked = $true
concernant le
-f
vous pouvez lire l’article : variables dans les chaines de caractères
Synthèse
Script
$i = 1
Pour creer un nom de variable dynamqiue :
New-Variable -Name "MaVar$i" -Value 'test'`
Pour récupérer une valeur avec un nom de variable dynamique
Get-Variable -Name "Mavar$i" -ValueOnly
GUI
$i = Poire
Pour agir sur un element GUI
(Get-Variable -name "Checkbox{0}" -f $i)).value.Checked = $true
Pour récupérer une valeur avec un nom de variable dynamique
(Get-Variable -name "Checkbox{0}" -f $i)).value.CheckState
Conclusion
Voia Voila… Dans cet article, je n’ai pas eu la volonté d’être exhaustif, il y a donc peut-être d’autres méthodes… Ce que je sais c’est que ce que je vous propose fonctionne. Cependant, si vous avez envie de partager d’autres méthode, n’hésitez pas, je les ajouterai, n’hésitez pas non plus à laisser un commentaire, cela fait toujours plaisir d’avoir un retour.
Update
@Thierry Degols m’a fait remarquer qu’une solution de contournement est possible, pour les variables avec doubles quotes, en utilisant $($item.name)
Soit :
write-host "Je fais une $($item.name) avec une variable"
A vous de choisir entre ça et le -f
, en toute honnêteté j’utilise autant les doubles quotes que le -f, cela dépend de la variable et du contexte.
@Nicolas BAUDIN amène un élément supplémentaire concernant la récupération du contenu d’une variable avec Get-Variable
. En effet avec cette commande, les wildcard sont possible
exemple :
$vSwitch1 = "test"
$AllvSwitch = Get-Variable -Name "vSwitch?" -ValueOnly
# ? remplace un caractère après vSwitch
Ou
$vSwitch1 = "test"
$AllvSwitch = Get-Variable -Name "vSwitch*" -ValueOnly
#* remplace tous les caractères qui suivent vSwitch
Attention, Attention, Attention, l’utilisation de wildcard peut amener à avoir des valeurs que l’on ne souhaite pas… En effet cela va récupérer toutes les valeurs de votre scope.
Partons du principe que l’on a lancé une fois chacun des tests précédent
Si je lance :
$vSwitch10 = "test"
$AllvSwitch = Get-Variable -Name "vSwitch?" -ValueOnly
En principe il ne devrait rien me donner vu qu’il y a deux caractères après vSwitch, or là il me donne :
PS C:\> $vSwitch10 = "test"
$AllvSwitch = Get-Variable -Name "vSwitch?" -ValueOnly
$AllvSwitch
test
Pourquoi ? car il a encore en “mémoire” l’ancienne variable $vSwitch1, donc là il ne nous donne pas la valeur de $vSwitch10 mais celle de vSwitch1.
Donc vraiment à utiliser en connaissance de cause… Et si vous n’avez pas compris mon explication c’est qu’il ne faut pas utiliser les Wildcards. eheh.