繁体   English   中英

powershell 点源 function 参数覆盖局部变量

[英]powershell dot sourced function parameter overwrites local variables

我正在使用 powershell 点源来设置当前 scope 中的变量,并且遇到了一个有趣的功能。

function 的参数似乎也会覆盖任何同名的局部变量。

这是预期的吗?

我是否应该只使用 $global:MyVar 从其他脚本中设置本地 scope 中的变量?

# Given
function TestX([string]$X) 
{
   Write-Host "`$X = $X" 
}

# And variable $X
# Note that the variable name is the same as the parameter name in 'TestX'
$X = "MyValue"

PS> TestX $X
MyValue

PS> $X; TestX "123456"
MyValue
123456

PS> $X; . TestX "123456"
MyValue
123456

PS> $X; . TestX "123456"
123456
123456

编辑:扩大我想要完成的事情......

我有一组用于构建过程的脚本。 这些脚本用于针对多个环境。 每个环境(DEV、TEST、QA、PROD)都有不同的配置,它们应用不同的规则/设置/等。 这些配置存储在目录中。 在这些设置中,有一些 powershell 文件用于为该特定环境设置脚本范围的设置。 比如目标服务器URL,目标服务器UNC等。

在构建过程脚本中有一个 function Confirm-TargetEnvironmentVariables。 顾名思义,它检查环境变量是否已加载,如果没有,则加载它们。 此 function 散布在各种脚本文件/函数中,以确保当 function 使用这些脚本范围变量之一时,它已被设置。

我曾经用点源调用的是这个 function。

function Confirm-TargetEnvironmentVariables([string]$TargetEnvironment) 
{
   ...
}

# Like this..
. Confirm-TargetEnvironmentVariables "PROD"

这一切都很好。 直到我需要在来自多个环境的加载变量之间切换(例如,为了从 PROD 刷新 TEST,我需要来自两者的变量信息)。 事实上这仍然有效,除了在调用 Confirm-TargetEnvironmentVariables 的脚本中我已经有一个名为 $TargetEnvironment 的变量。 所以我试图这样做:

$SourceEnvironment = "PROD"
$TargetEnvironment = "TEST"

. Confirm-TargetEnvironmentVariables $SourceEnvironment

# Do stuff with loaded "PROD" variables...

. Confirm-TargetEnvironmentVariables $TargetEnvironment

# Do stuff with loaded "TEST" variables...

但发生的事情是这样的:

$SourceEnvironment = "PROD"
$TargetEnvironment = "TEST"

. Confirm-TargetEnvironmentVariables $SourceEnvironment

# Do stuff with loaded "PROD" variables...
# The value of $TargetEnvironment has been set to "PROD" by dot-sourcing!!

. Confirm-TargetEnvironmentVariables $TargetEnvironment

# Do stuff with loaded... "PROD" variables!!!

因此,这应该有望提供更多背景信息。 但最终它仍然提出了一个问题,为什么 dot-sourcing 在将变量引入本地 scope 时包含参数变量。 这是设计使然吗? 不过,我想不出这种情况是理想的行为。

应该只使用 $global:MyVar 从其他脚本中设置本地 scope 中的变量吗?

我建议您避免编写需要点源才能正常工作或写入全局变量的函数。

相反,使用Set-Variable-Scope参数写入调用 scope 中的变量:

function Test-SetVariable
{
  param([string]$Name,$Value)

  # '1' means "one level up", so it updates the variable in the caller's scope
  Set-Variable -Name $Name -Value $Value -Scope 1
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM