Параметр функции powershell dot sourced перезаписывает локальные переменные - PullRequest
0 голосов
/ 30 апреля 2020

Я использую точечный источник PowerShell для установки переменных в текущей области и обнаружил интересную особенность.

Похоже, что параметр функции также перезапишет любую локальную переменную с тем же именем.

Ожидается ли это?

Должен ли я просто использовать $ global: MyVar вместо установить переменные в локальной области видимости из других сценариев?

# 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

РЕДАКТИРОВАТЬ: Чтобы расширить то, что я пытаюсь сделать sh ...

У меня есть набор сценариев используется для процесса сборки. Эти сценарии используются для работы с несколькими средами. Существуют разные конфигурации для каждой среды (DEV, TEST, QA, PROD), в которых применяются разные правила / настройки / et c. Эти конфигурации хранятся в каталогах. Среди этих параметров есть некоторые файлы PowerShell, которые используются для настройки параметров всего сценария для этой конкретной среды. Например, URL целевого сервера, целевой сервер UN C, et c ..

Среди сценариев процесса сборки есть функция Confirm-TargetEnvironmentVariables. Как следует из названия, он проверяет, были ли загружены переменные среды, а если нет, загружает их. Эта функция разбросана по разным файлам / функциям сценария, чтобы гарантировать, что когда функция использует одну из этих переменных сценария, она была установлена.

Именно эту функцию я использовал для вызова с точечным источником.

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

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

Все это работало просто отлично. Пока у меня не было необходимости переключаться между загрузкой переменных из более чем 1 среды (например, для обновления TEST из PROD мне нужна информация о переменных из обоих). И на самом деле это все еще работает, за исключением того факта, что в скрипте, который вызывал 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!!!

Так что это должно обеспечить больше контекста, надеюсь. Но в конечном итоге все еще возникает вопрос о том, почему точечный источник включает переменные параметров при переносе переменных в локальную область. Это по замыслу? Я не могу придумать сценарий, где это было бы желаемым поведением.

1 Ответ

1 голос
/ 30 апреля 2020

Стоит ли просто использовать $ global: MyVar вместо того, чтобы устанавливать переменные в локальной области из других сценариев?

Я бы порекомендовал вам избегать написания функций, для работы которых требуется точка-источник. правильно, или что запись в глобальные переменные.

Вместо этого используйте параметр Set-Variable -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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...