Setting a global PowerShell variable from a function where the global variable name is a variable passed to the function

前端 未结 7 1281
北荒
北荒 2020-12-04 16:17

I need to set a global variable from a function and am not quite sure how to do it.

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

function foo ($a,         


        
相关标签:
7条回答
  • 2020-12-04 16:49

    You can use the Set-Variable cmdlet. Passing $global:var3 sends the value of $var3, which is not what you want. You want to send the name.

    $global:var1 = $null
    
    function foo ($a, $b, $varName)
    {
       Set-Variable -Name $varName -Value ($a + $b) -Scope Global
    }
    
    foo 1 2 var1
    

    This is not very good programming practice, though. Below would be much more straightforward, and less likely to introduce bugs later:

    $global:var1 = $null
    
    function ComputeNewValue ($a, $b)
    {
       $a + $b
    }
    
    $global:var1 = ComputeNewValue 1 2
    
    0 讨论(0)
  • 2020-12-04 16:49

    @zdan. Good answer. I'd improve it like this...

    I think that the closest you can come to a true return value in PowerShell is to use a local variable to pass the value and never to use return as it may be 'corrupted' by any manner of output situations

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

    The $restart variable is used either side of the call to the function CheckRestart making clear the scope of the variable. The return value can by convention be either the first or last parameter declared. I prefer last.

    0 讨论(0)
  • 2020-12-04 16:53

    For me it worked:

    function changeA2 () { $global:A="0"}
    changeA2
    $A
    
    0 讨论(0)
  • 2020-12-04 16:57

    I ran across this question while troubleshooting my own code.

    So this does NOT work...

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

    This APPEARS to work, but only in the PowerShell ISE:

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

    This is actually what works in both ISE and command line:

    $global:myLogText = ""
    function AddLog ($Message)
    {
        $global:myLogText += ($Message)
    }
    AddLog ("Hello")
    Write-Host $global:myLogText
    
    0 讨论(0)
  • 2020-12-04 16:58

    The first suggestion in latkin's answer seems good, although I would suggest the less long-winded way below.

    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
    

    His second suggestion however about being bad programming practice, is fair enough in a simple computation like this one, but what if you want to return a more complicated output from your variable? For example, what if you wanted the function to return an array or an object? That's where, for me, PowerShell functions seem to fail woefully. Meaning you have no choice other than to pass it back from the function using a global variable. For example:

    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
    

    I know this might feel like a bit of a digression, but I feel in order to answer the original question we need to establish whether global variables are bad programming practice and whether, in more complex functions, there is a better way. (If there is one I'd be interested to here it.)

    0 讨论(0)
  • 2020-12-04 16:59

    You'll have to pass your arguments as reference types.

    #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
    
    0 讨论(0)
提交回复
热议问题