web-dev-qa-db-fra.com

Définition d'une variable globale PowerShell à partir d'une fonction où le nom de la variable globale est une variable transmise à la fonction

Je dois définir une variable globale à partir d'une fonction et je ne sais pas trop comment le faire.

# Set variables
$global:var1
$global:var2
$global:var3

function foo ($a, $b, $c)
{
    # Add $a and $b and set the requested global variable to equal to it
    $c = $a + $b
}

Appelez la fonction:

foo 1 2 $global:var3

Résultat final:

$ global: var3 est défini sur 3

Ou si j'ai appelé la fonction comme ceci:

foo 1 2 $global:var2

Résultat final:

$ global: var2 est défini sur 3

J'espère que cet exemple a du sens. La troisième variable transmise à la fonction est le nom de la variable à définir.

44
Radagast

Vous pouvez utiliser la cmdlet Set-Variable. Passer $global:var3 envoie le value de $var3, ce qui n'est pas ce que vous voulez. Vous voulez envoyer le name.

$global:var1 = $null

function foo ($a, $b, $varName)
{
   Set-Variable -Name $varName -Value ($a + $b) -Scope Global
}

foo 1 2 var1

Ce n'est cependant pas une très bonne pratique de programmation. Ci-dessous serait beaucoup plus simple, et moins susceptible d'introduire des bogues plus tard:

$global:var1 = $null

function ComputeNewValue ($a, $b)
{
   $a + $b
}

$global:var1 = ComputeNewValue 1 2
80
latkin

Aussi simple que:

$A="1"
function changeA2 () { $global:A="0"}
changeA2
$A
36
Kirt Carson

Vous devrez passer vos arguments en tant que types de référence. 

#First create the variables (note you have to set them to something)
$global:var1 = $null
$global:var2 = $null
$global:var3 = $null

#The type of the reference argument should be of type [REF]
function foo ($a, $b, [REF]$c)
{
    # add $a and $b and set the requested global variable to equal to it
    # Note how you modify the value.
    $c.Value = $a + $b
}

#You can then call it like this:
foo 1 2 [REF]$global:var3
17
zdan

J'ai rencontré cette question lors du dépannage de mon propre code.

Donc, cela ne fonctionne pas ...

$myLogText = ""
function AddLog ($Message)
{
    $myLogText += ($Message)
}
AddLog ("Hello")
Write-Host $myLogText

Cela semble fonctionner, mais uniquement dans le PowerShell ISE :

$myLogText = ""
function AddLog ($Message)
{
    $global:myLogText += ($Message)
}
AddLog ("Hello")
Write-Host $myLogText

C'est ce qui fonctionne à la fois dans ISE et en ligne de commande:

$global:myLogText = ""
function AddLog ($Message)
{
    $global:myLogText += ($Message)
}
AddLog ("Hello")
Write-Host $global:myLogText
14
da_jokker

La première suggestion dans la réponse de Latkin semble bonne, bien que je suggère la voie la moins longue en dessous.

PS c:\temp> $global:test="one"

PS c:\temp> $test
one

PS c:\temp> function changet() {$global:test="two"}

PS c:\temp> changet

PS c:\temp> $test
two

Sa seconde suggestion, cependant, à propos d’une mauvaise pratique de programmation, est assez juste dans un calcul simple comme celui-ci, mais qu’en est-il si vous voulez retourner une sortie plus compliquée de votre variable? Par exemple, si vous vouliez que la fonction retourne un tableau ou un objet? C’est là que, pour moi, les fonctions de PowerShell semblent échouer lamentablement. Cela signifie que vous n'avez pas d'autre choix que de le renvoyer de la fonction à l'aide d'une variable globale. Par exemple:

PS c:\temp> function changet([byte]$a,[byte]$b,[byte]$c) {$global:test=@(($a+$b),$c,($a+$c))}

PS c:\temp> changet 1 2 3

PS c:\temp> $test
3
3
4

PS C:\nb> $test[2]
4

Je sais que cela peut sembler être un peu une digression, mais je pense que pour répondre à la question initiale, nous devons déterminer si les variables globales sont une mauvaise pratique de programmation et si, dans des fonctions plus complexes, il existe un meilleur moyen. (S'il y en a un, cela m'intéresserait.)

1
AutoMattTick

@zdan. Bonne réponse. Je l'améliorerais comme ça ...

Je pense que le plus proche possible d'une valeur de retour vraie dans PowerShell consiste à utiliser une variable locale pour transmettre la valeur et à ne jamais utiliser return car elle peut être "corrompue" par tout type de situation

function CheckRestart([REF]$retval)
{
    # Some logic
    $retval.Value = $true
}
[bool]$restart = $false
CheckRestart( [REF]$restart)
if ( $restart )
{
    Restart-Computer -Force
}

La variable $restart est utilisée de part et d'autre de l'appel de la fonction CheckRestart en précisant le champ d'application de la variable. La valeur de retour peut par convention être le premier ou le dernier paramètre déclaré. Je préfère dernier.

1
RobG

Pour moi cela a fonctionné:

function changeA2 () { $global:A="0"}
changeA2
$A
0
user3360589