about_Scopes

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

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

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

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

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

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

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

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

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

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

Примечание.

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

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

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

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

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

Get-Variable -Scope local

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

Get-Variable -Scope global

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

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

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

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

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

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

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

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

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

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

    Примечание.

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

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

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

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

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

    Пространство имен Description
    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 *

Обратите внимание на значения свойств Видимости и параметров .

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, SSH Подключение ion или Session (удаленный сеанс)
  • Фоновые задания, запущенные с Start-Job (сеанс вне процесса)
  • Задания потоков, запущенные через Start-ThreadJob или ForEach-Object -Parallel (отдельный сеанс потока)

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

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

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

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

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

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

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

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

Параметр AllScope

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

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

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

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

Get-Help * -Parameter scope

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

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

Get-Variable -Scope local

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

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

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

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

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

Примечание.

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

Использование нотации dot-source с область

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

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

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

c:\scripts\sample.ps1

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

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

& 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 в обоих область.

$a = Hello
$global:a = Goodbye

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

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

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

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

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

Приватный параметр

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

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

Параметр Option для New-VariableSet-VariableNew-Aliasкомандлетов и Set-Alias командлетов можно использовать для задания значения свойства Option значение Private.

Visibility

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

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

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

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

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

Примеры

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

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

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

PS>  $ConfirmPreference
High

Создайте скрипт 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. Изменение значения переменной в родительском область

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

Сначала определите переменную $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: модификатора область или путем создания переменной с заданным Privateсвойством Option. Частные переменные можно просматривать или изменять только в область, в которой они были созданы.

В этом примере 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.

См. также