ПРИМЕЧАНИЕ. Я использую 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
Поведение, которое я ожидал, было для блока script, который я передал Test, чтобы повлиять на локальную область теста. Он находится в "dotsourced", поэтому любые изменения, которые он делает, должны находиться в пределах области вызова. Однако это не то, что происходит, это, по-видимому, влияет на сферу применения, где оно было объявлено. Здесь вывод:
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 влияет только на область проверки и не изменяет глобальную область.
Я не гуру PowerShell, но может ли кто-нибудь объяснить это поведение мне?