Поиск по сайту:

Области в PowerShell


Во многих языках программирования есть понятие области видимости. Определяется тем, какие переменные и функции доступны в каком контексте. Например, если переменная доступна для каждой функции в сценарии PowerShell или только для одной определенной функции. Области PowerShell охватывают несколько различных областей, которые можно использовать, например глобальные, локальные области или области сценария.

Что такое области PowerShell?

Как упоминалось во введении, существует несколько основных областей. Это глобальные, локальные и сценарии, которые сообщают PowerShell, какие переменные и функции доступны в каком контексте. При обращении к областям обычно используются префиксы областей для доступа к переменным за пределами текущей локальной области. Это проще всего понять на примерах.

Глобальный охват

Глобальная область означает, что переменная будет доступна для всех функций и команд независимо от их местоположения, например $MyVar=$True или $Global:MyVar=$True. При запуске PowerShell все исходные переменные имеют глобальную область действия. Если дочерних областей нет, глобальная область совпадает с локальной областью и областью сценария, пока не существуют дочерние области.

# This is in the Global scope
$MyVar = $True

Function Test-VariableScope {
	# When a variable is not found in the current scope, look up till it is found
	Write-Host "Global Scope: $MyVar"
	# Redefine the variable in the Local scope
	$MyVar = $False
	Write-Host "Local Scope: $MyVar"
	Write-Host "Global Scope: $($Global:MyVar)"
}

Test-VariableScope

# Since the Locally scoped variable does not exist anymore, return the Global scope
Write-Host "Global Scope: $MyVar"

Локальный охват

Текущая область всегда локальна и, следовательно, также является областью по умолчанию. Если для переменной не используется модификатор области, область действия является локальной, например $MyVar=$True. Локальную область может быть трудно понять, поскольку эта область относится к текущему местоположению, а локальная переменная может находиться в разных областях одновременно.

# This is in the Local scope (and Global scope since at root of script)
$MyVar = $True
Write-Host "Local Scope: $MyVar"
Write-Host "Local Scope Explicit: $($Local:MyVar)"
Function Test-VariableScope {
	# This variable is in the Local scope relative to Test-VariableScope
	$MyVar = $False
	Write-Host "Local Scope: $MyVar"
	Write-Host "Local Scope (Explicit): $($Local:MyVar)"
}

Test-VariableScope
# This variable is back to the local scope initially defined
Write-Host "Local Scope: $MyVar"
Write-Host "Local Scope Explicit: $($Local:MyVar)"

Когда вы используете точечный источник сценария, например . my-script.ps1, вы добавите весь вывод этого скрипта в локальную область!

Область сценария

Наконец, область сценария немного сложнее. Это либо ближайшая область файла сценария предка, либо глобальная область, если она не выполняется в файле сценария, таком как $script:var=$true. Глобальная, сценарная и локальная области видимости одинаковы для переменной $MyVar=$True при использовании в одном скрипте и даже в функциях.

# This is in the Script scope including Script and Local scope
$MyVar = $True
Write-Host "Script Scope: $($Script:MyVar)"

Function Test-VariableScope {
	# This variable is in the Local scope relative to Test-VariableScope
  $MyVar = $False
  # The Script scope references the same as $MyVar variable initially defined
	Write-Host "Script Scope: $($Script:MyVar)"
}

Test-VariableScope
# This variable is back to the Script scope initially defined
Write-Host "Script Scope: $($Script:MyVar)"

В отличие от точечного источника сценария, который добавляет все в локальную область, использование оператора вызова & запустит сценарий, но оставит все в области действия сценария, которая относится к самому сценарию.

Что такое параметры Private, Using, Workflow и AllScope?

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

Модификатор частной области

Когда вы определяете переменную или псевдоним как частную, переменная или псевдоним видны и могут быть изменены только в этом контексте. Как видно из приведенного ниже примера, приватная версия

Remove-Variable TestVar
Remove-Variable TestVar2
Remove-Variable TestVar3

# Two ways to create a private variable, note that this is an Option and not a Scope (applied to a scoped variable)
New-Variable -Name 'TestVar' -Value $True -Scope 'Global' -Option 'Private'
$Private:TestVar2 = $True

Write-Host "Global Scope (TestVar): $TestVar"
Write-Host "Global Scope (TestVar2): $TestVar"

$TestVar3 = $True

Function Test-Function {
  # Since the first two variables are private they are not seen
  Write-Host "Local Scope (TestVar): $TestVar"
  Write-Host "Local Scope (TestVar2): $TestVar2"
  # TestVar3 does not exist locally so PowerShell looks up and finds a non-Private variable in Global
  Write-Host "Local Scope (TestVar3): $TestVar3"
}

Test-Function

Что такое модификатор использования?

Это специальная переменная, которая используется командлетами и конструкциями Invoke-Command, Start-Job, Start-ThreadJob или . ForEach-Object -Parallel. Это будет работать только с Invoke-Command, когда он запускается на удаленном компьютере, например, с параметром ComputerName.

# Normally the LocalCSVData variable will not be available to the scriptblock running on the remote computer without the Using modifier.
$LocalCSVData = Import-CSV -Path 'mydata.csv'

Invoke-Command -ComputerName 'RemoteComputer' -ScriptBlock {
	$Using:LocalCSVData | ForEach-Object {
		...do something...
	}
}

Рабочий процесс и AllScope

Хотя они используются гораздо реже, есть два дополнительных модификатора. Модификатор Workflow используется для ссылки на переменные в рабочем процессе PowerShell (недоступно в PowerShell Core/7). Модификатор AllScope сделает переменную доступной во всех областях. Это также означает, что если переменная изменена в дочерней области, это отразится на корневых областях. Это один из способов избежать префикса глобальной переменной при попытке сослаться на нее в дочерних областях.

Заключение

Области полезны для ограничения видимости и доступности переменных, функций и псевдонимов. Области также могут вызывать проблемы, когда неясно, в какой области находится переменная. Надеюсь, эта статья прольет свет на то, как области используются в PowerShell и что вы можете с ними делать!