ПРИМЕЧАНИЕ. Я использую PowerShell 2.0 в Windows Vista.
Я пытаюсь добавить поддержку указания аргументов сборки в 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 как модуль, а вместо этого просто объявляю функцию и вызываю ее, все работает так, как я и ожидал. Блок script влияет только на область Test и не изменяет глобальную область.
Я не гуру PowerShell, но может ли кто-нибудь объяснить мне это поведение?