从全局变量名称是传递给函数的变量的函数设置全局PowerShell变量

从全局变量名称是传递给函数的变量的函数设置全局PowerShell变量,powershell,Powershell,我需要从一个函数中设置一个全局变量,但不太确定如何设置 # 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 } 调用函数: foo 1 2 $global:var3 最终结果: $global:var

我需要从一个函数中设置一个全局变量,但不太确定如何设置

# 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
}
调用函数:

foo 1 2 $global:var3
最终结果:

$global:var3设置为3

或者如果我像这样调用函数:

foo 1 2 $global:var2
最终结果:

$global:var2设置为3


我希望这个例子有意义。传递给函数的第三个变量是要设置的变量的名称。

必须将参数作为引用类型传递

#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

您可以使用
Set变量
cmdlet。传递
$global:var3
会发送
$var3
值,这不是您想要的。您想发送名称

$global:var1 = $null

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

foo 1 2 var1
不过,这不是很好的编程实践。下面将更加直观,并且不太可能在以后引入bug:

$global:var1 = $null

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

$global:var1 = ComputeNewValue 1 2
简单到:

$A="1"
function changeA2 () { $global:A="0"}
changeA2
$A
对我来说,它奏效了:

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

@兹丹。回答得好。我会像这样改进它


我认为,在PowerShell中,最接近真实返回值的方法是使用局部变量传递值,而不要使用
return
,因为它可能会被任何形式的输出情况“损坏”

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

$restart
变量用于调用函数
CheckRestart
的任意一侧,以明确变量的范围。按照惯例,返回值可以是声明的第一个或最后一个参数。我更喜欢最后一个。

我在对自己的代码进行故障排除时遇到了这个问题

所以这不起作用

$myLogText = ""
function AddLog ($Message)
{
    $myLogText += ($Message)
}
AddLog ("Hello")
Write-Host $myLogText
这似乎有效,但仅在以下情况下有效:

这实际上在ISE和命令行中都起作用:

$global:myLogText = ""
function AddLog ($Message)
{
    $global:myLogText += ($Message)
}
AddLog ("Hello")
Write-Host $global:myLogText
中的第一个建议似乎很好,尽管我建议下面的方法不太冗长

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
然而,他的第二个关于糟糕编程实践的建议,在像这样的简单计算中已经足够公平了,但是如果您想从变量返回更复杂的输出呢?例如,如果希望函数返回数组或对象,该怎么办?对我来说,这就是PowerShell功能失败的原因。这意味着您别无选择,只能使用全局变量将其从函数传回。例如:

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

我知道这可能有点离题,但我觉得为了回答最初的问题,我们需要确定全局变量是否是糟糕的编程实践,以及在更复杂的函数中是否有更好的方法。(如果这里有我感兴趣的话。)

@Schiavini——我想它确实有用。如果它让您感到厌烦,请记住,如果直接在cmd行中输入,那么第一个
$A
是全局的,并且在全局范围内尝试时应该被覆盖。如果需要,请尝试在之后添加行
$global:A
。这里有一个通过分号的单行程序,它接受参数并执行相同的操作:
$a=-777;函数changeA2($p1,$p2){$global:A=$p1+$p2};变化2 4 5$A.“显式全局:”+$global:A现在是可怕的意大利面代码吗?这是一个单独的讨论我倾向于拉特金的第二种解决方案。我认为,在PoSH中,最接近真实返回值的方法是使用局部变量传递值,并且永远不要使用
return
,因为它可能会被任何形式的输出情况
函数CheckRestart([REF]$retval){#某些逻辑$retval.value=$true}[bool]$restart=$false CheckRestart([REF]$restart)如果($restart){restart Computer-Force}
我可以在用户配置文件中使用Set变量cmdlet吗?因此,每当电脑启动时,它都会有一个全局变量?当我尝试使用powershell_ise执行profile.ps1时,它会正常执行。当我尝试使用&$profile执行配置文件时,我遇到了一个错误参数bingingValidationException,我甚至无法使第三个示例工作-仍然无法通过命令行分配(在VS和ISE上工作),我对这种powershell的怪异感到非常恼火!在我看来,在顶层(而不是在函数中)声明一个变量应该是全局的,对我来说是有意义的!是的,但只有在ISE中才有!因此,您编写代码,然后它在控制台中断,因为您在声明变量时没有使用$global:。在主脚本主体中声明的变量怎么可能不是全局的呢?更奇怪的是,对于具有属性的自定义对象,不需要使用$global。无需$global即可从任何地方访问它们:您现在可以发表评论。。这是一个好主意。
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