注意:我在 Windows Vista 上使用 PowerShell 2.0。
我正在尝试添加对指定构建参数的支持psake,但我遇到了一些奇怪的 PowerShell 变量作用域行为,专门处理使用 Export-ModuleMember 导出的调用函数(这是 psake 公开它的主要方法的方式)。下面是一个简单的 PowerShell 模块来说明(名为 repoCase.psm1):
function Test {
param(
[Parameter(Position=0,Mandatory=0)]
[scriptblock]$properties = {}
)
$defaults = {$message = "Hello, world!"}
Write-Host "Before running defaults, message is: $message"
. $defaults
#At this point, $message is correctly set to "Hellow, world!"
Write-Host "Aftering running defaults, message is: $message"
. $properties
#At this point, I would expect $message to be set to whatever is passed in,
#which in this case is "Hello from poperties!", but it isn't.
Write-Host "Aftering running properties, message is: $message"
}
Export-ModuleMember -Function "Test"
要测试模块,请运行以下命令序列(确保您与 repoCase.psm1 位于同一目录中):
Import-Module .\repoCase.psm1
#Note that $message should be null
Write-Host "Before execution - In global scope, message is: $message"
Test -properties { "Executing properties, message is $message"; $message = "Hello from properties!"; }
#Now $message is set to the value from the script block. The script block affected only the global scope.
Write-Host "After execution - In global scope, message is: $message"
Remove-Module repoCase
我期望的行为是我传递给 Test 的脚本块影响 Test 的本地范围。它正在被“点源化”,因此它所做的任何更改都应该在调用者的范围内。但是,这不是正在发生的事情,它似乎正在影响它被声明的范围。这是输出:
Before execution - In global scope, message is:
Before running defaults, message is:
Aftering running defaults, message is: Hello, world!
Executing properties, message is
Aftering running properties, message is: Hello, world!
After execution - In global scope, message is: Hello from properties!
有趣的是,如果我不将 Test 作为模块导出,而只是声明函数并调用它,那么一切都会像我期望的那样工作。脚本块只影响 Test 的作用域,不会修改全局作用域。
我不是 PowerShell 专家,但有人可以向我解释这种行为吗?