Поделиться через


about_Scopes

Краткое описание

Описывает концепцию область в PowerShell и показывает, как задать и изменить область элементов.

Подробное описание

PowerShell защищает доступ к переменным, псевдонимам, функциям и дискам PowerShell (PSDrive), ограничивая их чтение и изменение. PowerShell использует правила область, чтобы не вносить непреднамеренные изменения в элементы в других областях.

Правила области

При запуске PowerShell узел (pwsh.exe) создает пространство выполнения PowerShell. Ведущие процессы могут иметь несколько пространств выполнения. Каждое пространство выполнения имеет собственное состояние сеанса и область контейнеров. Доступ к состоянию и областям сеанса невозможно получить в экземплярах пространства выполнения.

Ниже приведены основные правила область.

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

Родительская и дочерняя области

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

Примечание

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

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

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

Чтобы найти элементы в определенном область, используйте параметр Scope или Get-VariableGet-Alias.

Например, чтобы получить все переменные в локальном область, введите:

Get-Variable -Scope local

Чтобы получить все переменные в глобальном область, введите:

Get-Variable -Scope global

Если ссылка делается на переменную, псевдоним или функцию, PowerShell выполняет поиск текущего область. Если элемент не найден, выполняется поиск родительского область. Этот поиск повторяется до глобального область. Если переменная является частной в родительском область, поиск продолжается по цепочке область. В примере 4 показан эффект частной переменной при поиске область.

Имена областей PowerShell

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

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

Для командлетов, поддерживающих области, на области можно ссылаться с помощью числа, описывающего относительное положение одного область к другому. Область 0 обозначает текущее (локальное) область, область 1 — родитель текущего область, область 2 — бабушка и дедушка текущего область. Этот шаблон продолжается до тех пор, пока вы не достигнете корневого область.

Модификаторы области

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

  • global:— указывает, что имя существует в глобальном область.

  • local:— указывает, что имя существует в локальном область. Текущим область всегда является локальный область.

  • private:— указывает, что имя — Private и отображается только для текущего область.

    Примечание

    private:не является область. Это параметр, который изменяет специальные возможности элемента за пределами область, в котором он определен.

  • script:— указывает, что имя существует в область скрипта. Область скрипта — это область файла скрипта ближайшего предка или глобальный, если ближайший файл скрипта-предка отсутствует.

  • using:— используется для доступа к переменным, определенным в другом область при выполнении скриптов с помощью командлетов, таких как Start-Job и Invoke-Command.

  • workflow: — указывает, что имя существует в рабочем процессе. Примечание. Рабочие процессы не поддерживаются в PowerShell версии 6 и более поздних версий.

  • <variable-namespace> — модификатор, созданный поставщиком PowerShell PSDrive . Пример:

    Пространство имен Описание
    Alias: Псевдонимы, определенные в текущем область
    Env: Переменные среды, определенные в текущем область
    Function: Функции, определенные в текущем область
    Variable: Переменные, определенные в текущем область

По умолчанию область для скриптов является область скриптов. Область по умолчанию для функций и псевдонимов — это локальные область, даже если они определены в скрипте.

Использование модификаторов область

Чтобы указать область новой переменной, псевдонима или функции, используйте модификатор область.

Синтаксис модификатора область в переменной:

$[<scope-modifier>:]<name> = <value>

Синтаксис модификатора область в функции:

function [<scope-modifier>:]<name> {<function-body>}

Следующая команда, которая не использует модификатор область, создает переменную в текущем или локальном область:

$a = "one"

Чтобы создать ту же переменную в глобальном область, используйте модификатор областьglobal::

$global:a = "one"
Get-Variable a | Format-List *

Обратите внимание на значения свойств Visibility и Options .

Name        : a
Description :
Value       : one
Visibility  : Public
Module      :
ModuleName  :
Options     : None
Attributes  : {}

Сравните это с частной переменной:

$private:pVar = 'Private variable'
Get-Variable pVar | Format-List *

С помощью модификатора private область свойству Options присваивается значение Private.

Name        : pVar
Description :
Value       : Private variable
Visibility  : Public
Module      :
ModuleName  :
Options     : Private
Attributes  : {}

Чтобы создать ту же переменную в область скрипта, используйте модификатор script: область:

$script:a = "one"

Также можно использовать модификатор область с функциями. Следующее определение функции создает функцию в глобальном область:

function global:Hello {
  Write-Host "Hello, World"
}

Модификаторы область также можно использовать для ссылки на переменную в другом область. Следующая команда ссылается на $test переменную сначала в локальном область, а затем в глобальном область:

$test
$global:test

Модификатор области using:

Использование — это специальный модификатор область, определяющий локальную переменную в удаленной команде. Без модификатора PowerShell ожидает, что переменные в удаленных командах будут определены в удаленном сеансе.

Модификатор using область появился в PowerShell 3.0.

Для любого скрипта или команды, выполняемых вне сеанса, требуется using модификатор область для внедрения значений переменных из вызывающего сеанса область, чтобы код вне сеанса смог получить к ним доступ. Модификатор using область поддерживается в следующих контекстах:

  • Удаленно выполняемые команды, запущенные с Invoke-Command использованием параметров ComputerName, HostName, SSHConnection или Session (удаленный сеанс)
  • Фоновые задания, запущенные с Start-Job (внепроцессный сеанс)
  • Задания потока, запущенные с помощью Start-ThreadJob или ForEach-Object -Parallel (отдельный сеанс потока)

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

Дополнительные сведения см. в разделе about_Remote_Variables.

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

Дополнительные сведения см. в разделах:

Сериализация значений переменных

Удаленно выполняемые команды и фоновые задания выполняются вне процесса. Внепроцессные сеансы используют сериализацию на основе XML и десериализацию, чтобы сделать значения переменных доступными через границы процесса. Процесс сериализации преобразует объекты в PSObject , содержащий свойства исходных объектов, но не его методы.

Для ограниченного набора типов десериализация восстанавливает объекты обратно в исходный тип. Восстановленный объект является копией исходного экземпляра объекта. Он содержит свойства и методы типа. Для простых типов, таких как System.Version, копия является точной. Для сложных типов копия несовершенна. Например, восстановленные объекты сертификата не включают закрытый ключ.

Экземпляры всех остальных типов являются экземплярами PSObject . Свойство PSTypeNames содержит исходное имя типа с префиксом Deserialized, например Deserialized.System.Data.DataTable

Параметр AllScope

Переменные и псевдонимы имеют свойство Option , которое может принимать значение AllScope. Элементы со свойством AllScope становятся частью создаваемых дочерних областей, хотя они не наследуются родительскими областями задним числом.

Элемент со свойством AllScope отображается в дочернем область и является частью этого область. Изменения элемента в любом область повлиять на все области, в которых определена переменная.

Управление область

Несколько командлетов имеют параметр Scope, который позволяет получать или задавать (создавать и изменять) элементы в определенном область. Используйте следующую команду, чтобы найти все командлеты в сеансе с параметром Scope :

Get-Help * -Parameter scope

Чтобы найти переменные, видимые в определенном область, используйте Scope параметр .Get-Variable Видимые переменные включают глобальные переменные, переменные в родительском область и переменные в текущем область.

Например, следующая команда возвращает переменные, видимые в локальной область:

Get-Variable -Scope local

Чтобы создать переменную в определенном область, используйте модификатор область или параметр Scope .Set-Variable Следующая команда создает переменную в глобальном область:

New-Variable -Scope global -Name a -Value "One"

Для указания область можно также использовать параметр New-AliasScope командлетов , Set-Aliasили Get-Alias . Следующая команда создает псевдоним в глобальном область:

New-Alias -Scope global -Name np -Value Notepad.exe

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

Примечание

Для командлетов, использующих параметр Scope , можно также ссылаться на области по числу. Число описывает относительное положение одного область к другому. Область 0 представляет текущий или локальный область. Область 1 указывает непосредственное родительское область. Область 2 указывает родительский элемент родительского область и т. д. Нумерованные области полезны, если вы создали много рекурсивных областей.

Использование точечной нотации с область

Скрипты и функции следуют правилам область. Они создаются в определенном область, и они влияют только на область, если для изменения область не используется параметр командлета или модификатор область.

Но вы можете добавить содержимое скрипта или функции в текущий область с помощью нотации из источника точек. При выполнении скрипта или функции с использованием нотации dot-source они выполняются в текущем область. Все функции, псевдонимы и переменные в скрипте или функции добавляются в текущий область.

Например, чтобы запустить Sample.ps1 скрипт из C:\Scripts каталога в область скрипта (по умолчанию для скриптов), просто введите полный путь к файлу скрипта в командной строке.

c:\scripts\sample.ps1

Файл скрипта .ps1 должен иметь расширение файла, чтобы быть исполняемым. Файлы с пробелами в пути должны быть заключены в кавычки. При попытке выполнить путь в кавычках PowerShell отображает содержимое строки в кавычках вместо запуска скрипта. Оператор вызова (&) позволяет выполнить содержимое строки, содержащей имя файла.

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

& c:\scripts\sample.ps1

Дополнительные сведения об операторе вызова см. в about_Operators.

Чтобы запустить Sample.ps1 скрипт в локальной область введите точку и пробел (. ) перед путем к скрипту:

. c:\scripts\sample.ps1

Теперь все функции, псевдонимы или переменные, определенные в скрипте, добавляются в текущий область.

Ограничение без область

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

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

Сеансы

Сеанс — это среда, в которой выполняется PowerShell. При создании сеанса на удаленном компьютере PowerShell устанавливает постоянное подключение к удаленному компьютеру. Постоянное подключение позволяет использовать сеанс для нескольких связанных команд.

Так как сеанс является автономной средой, у него есть собственные область, но сеанс не является дочерним область сеанса, в котором он был создан. Сеанс начинается с собственного глобального область. Это область не зависит от глобального область сеанса. В сеансе можно создавать дочерние области. Например, можно запустить скрипт для создания дочернего область в сеансе.

Модули

Модуль PowerShell можно использовать для предоставления общего доступа к средствам PowerShell и их доставки. Модуль — это единица, которая может содержать командлеты, скрипты, функции, переменные, псевдонимы и другие полезные элементы. Если явно не экспортирован (с помощью Export-ModuleMember или манифеста модуля), элементы в модуле недоступны за пределами модуля. Таким образом, вы можете добавить модуль в сеанс и использовать общедоступные элементы, не беспокоясь о том, что другие элементы могут переопределить командлеты, скрипты, функции и другие элементы в сеансе.

По умолчанию модули загружаются в корневой (глобальный) область пространства выполнения. Импорт модуля не изменяет область. В рамках сеанса модули имеют собственные область. Рассмотрим следующий модуль C:\temp\mod1.psm1:

$a = "Hello"

function foo {
    "`$a = $a"
    "`$global:a = $global:a"
}

Теперь мы создадим глобальную переменную $a, присвоим ей значение и вызовем функцию foo.

$a = "Goodbye"
foo

Модуль объявляет переменную $a в модуле область затем функция foo выводит значение переменной в обеих областях.

$a = Hello
$global:a = Goodbye

Модули создают параллельные контейнеры область, связанные с область, в которую они были импортированы. Элементы, экспортированные модулем, доступны начиная с область уровня, на котором они импортируются. Элементы, не экспортированные из модуля, доступны только в контейнере область модуля. Функции в модуле могут обращаться к элементам в область, в котором они были импортированы, а также к элементам в контейнере область модуля.

При загрузке модуля Module2 из модуляModule1модуль 2 загружается в контейнер область модуля Module1. Все экспорты из Модуля 2 помещаются в текущий область модуля Module1. Если вы используете Import-Module -Scope local, экспорты помещаются в текущий объект область, а не на верхнем уровне. Если вы находитесь в модуле и загружаете другой модуль с помощью Import-Module -Scope global (или Import-Module -Global), этот модуль и его экспорты загружаются в глобальный область вместо локального область модуля. Функция WindowsCompatibility делает это для импорта прокси-модулей в состояние глобального сеанса.

Вложенные запросы

Вложенные запросы не имеют собственных область. При вводе вложенного запроса вложенный запрос является подмножеством среды. Но вы остаетесь в пределах местных область.

Скрипты имеют собственные область. Если выполняется отладка скрипта и достигается точка останова в скрипте, введите скрипт область.

Параметр "Частный"

Псевдонимы и переменные имеют свойство Option , которое может принимать значение Private. Элементы с параметром Private можно просматривать и изменять в область, в котором они созданы, но их нельзя просматривать или изменять вне область.

Например, если вы создаете переменную с частным параметром в глобальном область, а затем запускаете скрипт, Get-Variable команды в скрипте не будут отображать частную переменную. При использовании модификатора глобального область в этом экземпляре частная переменная не отображается.

Можно использовать параметр New-VariableOption командлетов , Set-Variable, New-Aliasи Set-Alias , чтобы задать для свойства Option значение Private.

Видимость

Свойство Visibility переменной или псевдонима определяет, можно ли увидеть элемент за пределами контейнера, в котором он был создан. Контейнер может быть модулем, скриптом или оснасткой. Видимость предназначена для контейнеров так же, как Private значение свойства Option предназначено для областей.

Свойство Visibility принимает Public значения и Private . Элементы с закрытой видимостью можно просматривать и изменять только в контейнере, в котором они были созданы. При добавлении или импорте контейнера элементы, имеющие частную видимость, не могут быть просмотрены или изменены.

Так как видимость предназначена для контейнеров, она работает по-разному в область.

  • Если вы создаете элемент, который имеет частную видимость в глобальном область, вы не сможете просматривать или изменять элемент в любом область.
  • При попытке просмотреть или изменить значение переменной с закрытой видимостью PowerShell возвращает сообщение об ошибке.

Командлеты и Set-Variable можно использовать New-Variable для создания переменной с частной видимостью.

Примеры

Пример 1. Изменение значения переменной только в скрипте

Следующая команда изменяет значение переменной $ConfirmPreference в скрипте. Изменение не влияет на глобальные область.

Во-первых, чтобы отобразить значение переменной $ConfirmPreference в локальной область, используйте следующую команду:

PS>  $ConfirmPreference
High

Create скрипт Scope.ps1, содержащий следующие команды:

$ConfirmPreference = "Low"
"The value of `$ConfirmPreference is $ConfirmPreference."

Выполните скрипт. Скрипт изменяет значение переменной, $ConfirmPreference а затем передает ее значение в область скрипта. Выходные данные должны выглядеть следующим образом:

The value of $ConfirmPreference is Low.

Затем проверьте текущее значение переменной $ConfirmPreference в текущем область.

PS>  $ConfirmPreference
High

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

Пример 2. Просмотр значения переменной в разных областях

Модификаторы область можно использовать для просмотра значения переменной в локальном область и родительском область.

Сначала определите переменную $test в глобальном область.

$test = "Global"

Затем создайте Sample.ps1 скрипт, определяющий переменную $test . В скрипте используйте модификатор область для ссылки на глобальную или локальную версию переменной$test.

В Sample.ps1:

$test = "Local"
"The local value of `$test is $test."
"The global value of `$test is $global:test."

При запуске Sample.ps1выходные данные должны выглядеть следующим образом:

The local value of $test is Local.
The global value of $test is Global.

После завершения скрипта в сеансе определяется только глобальное значение $test .

PS> $test
Global

Пример 3. Изменение значения переменной в родительском область

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

Сначала определите переменную $test в глобальном область.

$test = "Global"

Затем создайте скрипт Sample.ps1, определяющий переменную $test . В скрипте используйте модификатор область для ссылки на глобальную или локальную версию переменной$test.

В Sample.ps1:

$global:test = "Local"
"The global value of `$test is $global:test."

После завершения скрипта глобальное значение $test изменяется.

PS> $test
Local

Пример 4. Создание частной переменной

Переменная может быть закрыта с помощью модификатора private: область или путем создания переменной с свойством Option, для параметра задано значение Private. Частные переменные можно просматривать или изменять только в область, в котором они были созданы.

В этом примере ScopeExample.ps1 скрипт создает пять функций. Первая функция вызывает следующую функцию, которая создает дочерний область. Одна из функций имеет частную переменную, которую можно увидеть только в область, в которой она была создана.

PS> Get-Content ScopeExample.ps1
# Start of ScopeExample.ps1
function funcA {
    "Setting `$funcAVar1 to 'Value set in funcA'"
    $funcAVar1 = "Value set in funcA"
    funcB
}

function funcB {
    "In funcB before set -> '$funcAVar1'"
    $private:funcAVar1 = "Locally overwrite the value - child scopes can't see me!"
    "In funcB after set  -> '$funcAVar1'"
    funcC
}

function funcC {
    "In funcC before set -> '$funcAVar1' - should be the value set in funcA"
    $funcAVar1 = "Value set in funcC - Child scopes can see this change."
    "In funcC after set  -> '$funcAVar1'"
    funcD
}

function funcD {
    "In funcD before set -> '$funcAVar1' - should be the value from funcC."
    $funcAVar1 = "Value set in funcD"
    "In funcD after set  -> '$funcAVar1'"
    '-------------------'
    ShowScopes
}

function ShowScopes {
    $funcAVar1 = "Value set in ShowScopes"
    "Scope [0] (local)  `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 0 -ValueOnly)'"
    "Scope [1] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 1 -ValueOnly)'"
    "Scope [2] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 2 -ValueOnly)'"
    "Scope [3] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 3 -ValueOnly)'"
    "Scope [4] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 4 -ValueOnly)'"
}
funcA
# End of ScopeExample.ps1
PS> .\ScopeExample.ps1

В выходных данных показано значение переменной в каждом область. Вы видите, что частная переменная отображается только в funcBобласть, в котором она была создана.

Setting $funcAVar1 to 'Value set in funcA'
In funcB before set -> 'Value set in funcA'
In funcB after set  -> 'Locally overwrite the value - child scopes can't see me!'
In funcC before set -> 'Value set in funcA' - should be the value set in funcA
In funcC after set  -> 'Value set in funcC - Child scopes can see this change.'
In funcD before set -> 'Value set in funcC - Child scopes can see this change.' - should be the value from funcC.
In funcD after set  -> 'Value set in funcD'
-------------------
Scope [0] (local)  $funcAVar1 = 'Value set in ShowScopes'
Scope [1] (parent) $funcAVar1 = 'Value set in funcD'
Scope [2] (parent) $funcAVar1 = 'Value set in funcC - Child scopes can see this change.'
Scope [3] (parent) $funcAVar1 = 'Locally overwrite the value - child scopes can't see me!'
Scope [4] (parent) $funcAVar1 = 'Value set in funcA'

Как показано в выходных данных из ShowScopes, вы можете получить доступ к переменным из других областей с помощью Get-Variable и указания номера область.

Пример 5. Использование локальной переменной в удаленной команде

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

Синтаксис:

$using:<VariableName>

Например, следующие команды создают переменную $Cred в локальном сеансе, а затем используют $Cred ее в удаленной команде:

$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $using:Cred}

Модификатор using область появился в PowerShell 3.0.

См. также раздел