about_Scopes
Explica o conceito de escopo no PowerShell e mostra como definir e alterar o escopo dos elementos.
O PowerShell protege o acesso a variáveis, aliases, funções e unidades do PowerShell (PSDrives) limitando onde elas podem ser lidas e alteradas. O PowerShell usa regras de escopo para garantir que você não faça alterações não intencionais em itens em outros escopos.
Quando você inicia o PowerShell, o host (pwsh.exe
) cria um espaço de execução do PowerShell.
Os processos de host podem ter vários espaços de execução. Cada espaço de execução tem seu próprio estado de sessão e contêineres de escopo. O estado e os escopos da sessão não podem ser acessados entre instâncias de espaço de execução.
As regras básicas de âmbito de aplicação são as seguintes:
- Os escopos podem aninhar. Um escopo externo é chamado de escopo pai. Todos os escopos aninhados são escopos filhos desse pai.
- Um item é visível no escopo em que foi criado e em qualquer escopo filho, a menos que você o torne explicitamente privado.
- Você pode declarar variáveis, aliases, funções e unidades do PowerShell para um escopo fora do escopo atual.
- Um item que você criou dentro de um escopo pode ser alterado somente no escopo no qual foi criado, a menos que você especifique explicitamente um escopo diferente.
- Quando o código em execução em um espaço de execução faz referência a um item, o PowerShell pesquisa a hierarquia de escopo, começando com o escopo atual e prosseguindo por cada escopo pai.
- Se o item não for encontrado, um novo item será criado no escopo atual.
- Se encontrar uma correspondência, o valor do item será recuperado do escopo onde foi encontrado.
- Se você alterar o valor, o item será copiado para o escopo atual para que a alteração afete apenas o escopo atual.
- Se você criar explicitamente um item que compartilha seu nome com um item em um escopo diferente, o item original pode estar oculto pelo novo item, mas não é substituído ou alterado.
Você pode criar um novo escopo filho chamando um script ou função. O escopo de chamada é o escopo pai. O script ou função chamada é o escopo filho. As funções ou scripts que você chama podem chamar outras funções, criando uma hierarquia de escopos filho cujo escopo raiz é o escopo global.
Nota
As funções de um módulo não são executadas em um escopo filho do escopo de chamada. Os módulos têm seu próprio estado de sessão vinculado ao escopo no qual o módulo foi importado. Todo o código do módulo é executado em uma hierarquia de escopos específica do módulo que tem seu próprio escopo raiz. Para obter mais informações, consulte a seção Módulos deste artigo.
Quando um escopo filho é criado, ele inclui todos os aliases e variáveis que têm a opção AllScope e algumas variáveis automáticas. Esta opção é discutida mais adiante neste artigo.
A menos que você torne explicitamente os itens privados, os itens no escopo pai estarão disponíveis para o escopo filho. Os itens criados ou alterados em um escopo filho não afetam o escopo pai, a menos que você especifique explicitamente o escopo ao criar os itens.
Para localizar os itens em um escopo específico, use o parâmetro Scope de Get-Variable
ou Get-Alias
.
Por exemplo, para obter todas as variáveis no escopo local, digite:
Get-Variable -Scope local
Para obter todas as variáveis no escopo global, digite:
Get-Variable -Scope global
Quando uma referência é feita a uma variável, alias ou função, o PowerShell pesquisa o escopo atual. Se o item não for encontrado, o escopo pai será pesquisado. Essa busca se repete até o âmbito global. Se uma variável for privada em um escopo pai, a pesquisa continuará através da cadeia de escopo. O Exemplo 4 mostra o efeito de uma variável privada em uma pesquisa de escopo.
O PowerShell define nomes para alguns escopos para permitir um acesso mais fácil a esse escopo. O PowerShell define os seguintes escopos nomeados:
- Global: o escopo que está em vigor quando o PowerShell é iniciado ou quando você cria uma nova sessão ou espaço de execução. As variáveis e funções que estão presentes quando o PowerShell é iniciado, como variáveis automáticas e variáveis de preferência, são criadas no escopo global. As variáveis, aliases e funções em seus perfis do PowerShell também são criadas no escopo global. O escopo global é o escopo pai raiz em um espaço de execução.
- Local: O escopo atual. O escopo local pode ser o escopo global ou qualquer outro escopo.
- Script: o escopo criado enquanto um arquivo de script é executado. Os comandos no script são executados no escopo do script. Para os comandos em um script, o escopo do script é o escopo local.
Para cmdlets que oferecem suporte a escopos, os escopos podem ser referidos por um número que descreve a posição relativa de um escopo para outro. O escopo 0 denota o escopo atual (local), o escopo 1 é o pai do escopo atual, o escopo 2 é o avô do escopo atual. Esse padrão continua até que você atinja o escopo raiz.
Uma variável, alias ou nome de função pode incluir qualquer um dos seguintes modificadores de escopo opcionais:
global:
- Especifica que o nome existe no escopo Global .local:
- Especifica que o nome existe no escopo Local . O escopo atual é sempre o escopo Local .private:
- Especifica que o nome é Privado e visível apenas para o escopo atual.Nota
private:
não é um escopo. É uma opção que altera a acessibilidade de um item fora do escopo no qual ele está definido.script:
- Especifica que o nome existe no escopo do Script . Escopo de script é o escopo do arquivo de script ancestral mais próximo ou Global se não houver um arquivo de script ancestral mais próximo.using:
- Usado para acessar variáveis definidas em outro escopo durante a execução em sessões remotas, trabalhos em segundo plano ou trabalhos de thread.workflow:
- Especifica que o nome existe dentro de um fluxo de trabalho. Observação: os fluxos de trabalho não são suportados no PowerShell v6 e superior.<variable-namespace>
- Um modificador criado por um provedor PSDrive do PowerShell. Por exemplo:Espaço de Nomes Description Alias:
Aliases definidos no âmbito atual Env:
Variáveis de ambiente definidas no âmbito atual Function:
Funções definidas no âmbito atual Variable:
Variáveis definidas no âmbito atual
O escopo padrão para scripts é o escopo do script. O escopo padrão para funções e aliases é o escopo local, mesmo que eles sejam definidos em um script.
Para especificar o escopo de uma nova variável, alias ou função, use um modificador de escopo.
A sintaxe para um modificador de escopo em uma variável é:
$[<scope-modifier>:]<name> = <value>
A sintaxe para um modificador de escopo em uma função é:
function [<scope-modifier>:]<name> {<function-body>}
O comando a seguir, que não usa um modificador de escopo, cria uma variável no escopo atual ou local :
$a = "one"
Para criar a mesma variável no escopo global , use o modificador de escopo global:
:
$global:a = "one"
Get-Variable a | Format-List *
Observe os valores das propriedades Visibility e Options.
Name : a
Description :
Value : one
Visibility : Public
Module :
ModuleName :
Options : None
Attributes : {}
Compare isso com uma variável privada:
$private:pVar = 'Private variable'
Get-Variable pVar | Format-List *
O uso do private
modificador de escopo define a propriedade Options como Private
.
Name : pVar
Description :
Value : Private variable
Visibility : Public
Module :
ModuleName :
Options : Private
Attributes : {}
Para criar a mesma variável no escopo do script , use o modificador de script:
escopo:
$script:a = "one"
Você também pode usar um modificador de escopo com funções. A definição de função a seguir cria uma função no escopo global :
function global:Hello {
Write-Host "Hello, World"
}
Você também pode usar modificadores de escopo para se referir a uma variável em um escopo diferente.
O comando a seguir refere-se à $test
variável, primeiro no escopo local e depois no escopo global:
$test
$global:test
Usando é um modificador de escopo especial que identifica uma variável local em um comando remoto. Sem um modificador, o PowerShell espera que variáveis em comandos remotos sejam definidas na sessão remota.
O using
modificador de escopo é introduzido no PowerShell 3.0.
Para qualquer script ou comando executado fora da sessão, você precisa do using
modificador de escopo para incorporar valores de variáveis do escopo da sessão de chamada, para que o código fora da sessão possa acessá-los. O using
modificador de escopo é suportado nos seguintes contextos:
- Comandos executados remotamente, iniciados com
Invoke-Command
o uso dos parâmetros ComputerName, HostName, SSHConnection ou Session (sessão remota) - Trabalhos em segundo plano, iniciados com
Start-Job
(sessão fora do processo) - Trabalhos de thread, iniciados via
Start-ThreadJob
ouForEach-Object -Parallel
(sessão de thread separada)
Dependendo do contexto, os valores das variáveis incorporadas são cópias independentes dos dados no escopo do chamador ou referências a eles. Em sessões remotas e fora de processo, são sempre cópias independentes.
Para obter mais informações, consulte about_Remote_Variables.
Uma $using:
referência só se expande para o valor de uma variável. Se quiser alterar o valor de uma variável no escopo do chamador, você deve ter uma referência à própria variável. Você pode criar uma referência a uma variável obtendo a instância PSVariable da variável. O exemplo a seguir mostra como criar uma referência e fazer alterações em um trabalho de thread.
$Count = 1
$refOfCount = Get-Variable Count
Start-ThreadJob {
($using:refOfCount).Value = 2
} | Receive-Job -Wait -AutoRemoveJob
$Count
2
Nota
Esta não é uma operação thread-safe. Você pode causar corrupção de dados se tentar alterar o valor de vários threads ao mesmo tempo. Você deve usar tipos de dados thread-safe ou primitivos de sincronização para proteger dados compartilhados. Para obter mais informações, consulte Coleções Thread-Safe.
Comandos executados remotamente e trabalhos em segundo plano ficam fora do processo. As sessões fora de processo usam serialização e desserialização baseadas em XML para disponibilizar os valores das variáveis através dos limites do processo. O processo de serialização converte objetos em um PSObject que contém as propriedades dos objetos originais, mas não seus métodos.
Para um conjunto limitado de tipos, a desserialização reidrata os objetos de volta ao tipo original. O objeto reidratado é uma cópia da instância do objeto original. Tem as propriedades de tipo e métodos. Para tipos simples, como System.Version, a cópia é exata. Para tipos complexos, a cópia é imperfeita. Por exemplo, objetos de certificado reidratados não incluem a chave privada.
As instâncias de todos os outros tipos são instâncias PSObject . A propriedade PSTypeNames contém o nome do tipo original prefixado com Deserialized, por exemplo, Deserialized.System.Data.DataTable
Variáveis e aliases têm uma propriedade Option que pode ter um valor de AllScope. Os itens que têm a propriedade AllScope tornam-se parte de quaisquer escopos filho que você criar, embora não sejam herdados retroativamente pelos escopos pai.
Um item que tem a propriedade AllScope é visível no escopo filho e faz parte desse escopo. As alterações no item em qualquer escopo afetam todos os escopos nos quais a variável é definida.
Vários cmdlets têm um parâmetro Scope que permite obter ou definir (criar e alterar) itens em um escopo específico. Use o comando a seguir para localizar todos os cmdlets em sua sessão que têm um parâmetro Scope :
Get-Help * -Parameter scope
Para localizar as variáveis visíveis em um escopo específico, use o Scope
parâmetro de Get-Variable
. As variáveis visíveis incluem variáveis globais, variáveis no escopo pai e variáveis no escopo atual.
Por exemplo, o comando a seguir obtém as variáveis visíveis no escopo local:
Get-Variable -Scope local
Para criar uma variável em um escopo específico, use um modificador de escopo ou o parâmetro Scope de Set-Variable
. O comando a seguir cria uma variável no escopo global:
New-Variable -Scope global -Name a -Value "One"
Você também pode usar o parâmetro Scope dos New-Alias
cmdlets , Set-Alias
ou Get-Alias
para especificar o escopo. O comando a seguir cria um alias no escopo global:
New-Alias -Scope global -Name np -Value Notepad.exe
Para obter as funções em um escopo específico, use o Get-Item
cmdlet quando estiver no escopo. O Get-Item
cmdlet não tem um parâmetro Scope .
Nota
Para os cmdlets que usam o parâmetro Scope , você também pode fazer referência aos escopos por número. O número descreve a posição relativa de um escopo para outro. O escopo 0 representa o escopo atual ou local. O escopo 1 indica o escopo pai imediato. O escopo 2 indica o pai do escopo pai e assim por diante. Os escopos numerados são úteis se você tiver criado muitos escopos recursivos.
Scripts e funções seguem as regras de escopo. Você os cria em um escopo específico e eles afetam apenas esse escopo, a menos que você use um parâmetro de cmdlet ou um modificador de escopo para alterar esse escopo.
Mas, você pode adicionar o conteúdo de um script ou função ao escopo atual usando a notação ponto-fonte. Quando você executa um script ou função usando notação ponto-fonte, ele é executado no escopo atual. Quaisquer funções, aliases e variáveis no script ou função são adicionados ao escopo atual.
Por exemplo, para executar o Sample.ps1
script a C:\Scripts
partir do diretório no escopo do script (o padrão para scripts), basta digitar o caminho completo para o arquivo de script na linha de comando.
c:\scripts\sample.ps1
Um arquivo de script deve ter uma .ps1
extensão de arquivo para ser executável. Os arquivos que têm espaços em seu caminho devem ser colocados entre aspas. Se você tentar executar o caminho entre aspas, o PowerShell exibirá o conteúdo da cadeia de caracteres entre aspas em vez de executar o script. O operador de chamada (&
) permite que você execute o conteúdo da cadeia de caracteres que contém o nome do arquivo.
O uso do operador de chamada para executar uma função ou script o executa no escopo do script. Usar o operador de chamada não é diferente de executar o script pelo nome.
& c:\scripts\sample.ps1
Você pode ler mais sobre a operadora de chamadas em about_Operators.
Para executar o Sample.ps1
script no escopo local, digite um ponto e um espaço (.
) antes do caminho para o script:
. c:\scripts\sample.ps1
Agora, todas as funções, aliases ou variáveis definidas no script são adicionadas ao escopo atual.
O PowerShell tem algumas opções e recursos que são semelhantes ao escopo e podem interagir com escopos. Esses recursos podem ser confundidos com o escopo ou o comportamento do escopo.
Sessões, módulos e prompts aninhados são ambientes autônomos, não escopos filho do escopo global na sessão.
Uma sessão é um ambiente no qual o PowerShell é executado. Quando você cria uma sessão em um computador remoto, o PowerShell estabelece uma conexão persistente com o computador remoto. A conexão persistente permite que você use a sessão para vários comandos relacionados.
Como uma sessão é um ambiente contido, ela tem seu próprio escopo, mas uma sessão não é um escopo filho da sessão na qual foi criada. A sessão começa com o seu próprio âmbito global. Este âmbito é independente do âmbito global da sessão. Você pode criar escopos filho na sessão. Por exemplo, você pode executar um script para criar um escopo filho em uma sessão.
Você pode usar um módulo do PowerShell para compartilhar e entregar ferramentas do PowerShell. Um módulo é uma unidade que pode conter cmdlets, scripts, funções, variáveis, aliases e outros itens úteis. A menos que explicitamente exportados (usando Export-ModuleMember
ou o manifesto do módulo), os itens em um módulo não são acessíveis fora do módulo. Portanto, você pode adicionar o módulo à sua sessão e usar os itens públicos sem se preocupar que os outros itens possam substituir os cmdlets, scripts, funções e outros itens em sua sessão.
Por padrão, os módulos são carregados no escopo de nível raiz (global) do espaço de execução. A importação de um módulo não altera o escopo.
Dentro da sessão, os módulos têm seu próprio escopo. Considere o seguinte módulo C:\temp\mod1.psm1
:
$a = "Hello"
function foo {
"`$a = $a"
"`$global:a = $global:a"
}
Agora criamos uma variável $a
global, damos um valor a ela e chamamos a função de foo.
$a = "Goodbye"
foo
O módulo declara a variável $a
no escopo do módulo, em seguida, a função foo produz o valor da variável em ambos os escopos.
$a = Hello
$global:a = Goodbye
Os módulos criam contêineres de escopo paralelos vinculados ao escopo no qual foram importados. Os itens exportados pelo módulo estão disponíveis a partir do nível de escopo em que são importados. Os itens não exportados do módulo só estão disponíveis dentro do contêiner de escopo do módulo. As funções no módulo podem acessar itens no escopo em que foram importados, bem como itens no contêiner de escopo do módulo.
Se você carregar o Module2 de dentro do Module1, o Module2 será carregado no contêiner de escopo do Module1. Todas as exportações do Módulo2 são colocadas no escopo atual do módulo do Módulo1. Se você usar Import-Module -Scope local
o , as exportações serão colocadas no objeto de escopo atual em vez de no nível superior. Se você estiver em um módulo e carregar outro módulo usando Import-Module -Scope global
(ou Import-Module -Global
), esse módulo e suas exportações serão carregados no escopo global em vez do escopo local do módulo.
O recurso WindowsCompatibility faz isso para importar módulos proxy para o estado da sessão global.
Os prompts aninhados não têm seu próprio escopo. Quando você insere um prompt aninhado, o prompt aninhado é um subconjunto do ambiente. Mas, você permanece dentro do escopo local.
Os scripts têm seu próprio escopo. Se você estiver depurando um script e atingir um ponto de interrupção no script, insira o escopo do script.
Aliases e variáveis têm uma propriedade Option que pode ter um valor de Private
. Os itens que têm a Private
opção podem ser visualizados e alterados no âmbito em que são criados, mas não podem ser visualizados ou alterados fora desse âmbito.
Por exemplo, se você criar uma variável que tenha uma opção privada no escopo global e, em seguida, executar um script, Get-Variable
os comandos no script não exibirão a variável private. O uso do modificador de escopo global nesta instância não exibe a variável private.
Você pode usar o parâmetro Option dos New-Variable
cmdlets , Set-Variable
, New-Alias
e para Set-Alias
definir o valor da propriedade Option como Private.
A propriedade Visibility de uma variável ou alias determina se você pode ver o item fora do contêiner, no qual ele foi criado. Um contêiner pode ser um módulo, script ou snap-in. A visibilidade é projetada para contêineres da mesma forma que o Private
valor da propriedade Option é projetado para escopos.
A propriedade Visibility usa os Public
valores e Private
. Os itens que têm visibilidade privada podem ser visualizados e alterados apenas no contêiner no qual foram criados. Se o contêiner for adicionado ou importado, os itens que têm visibilidade privada não poderão ser exibidos ou alterados.
Como a visibilidade é projetada para contêineres, ela funciona de forma diferente em um escopo.
- Se você criar um item que tenha visibilidade privada no escopo global, não poderá exibir ou alterar o item em nenhum escopo.
- Se você tentar exibir ou alterar o valor de uma variável que tenha visibilidade privada, o PowerShell retornará uma mensagem de erro.
Você pode usar os New-Variable
cmdlets e Set-Variable
para criar uma variável que tenha visibilidade privada.
O comando a seguir altera o $ConfirmPreference
valor da variável em um script. A alteração não afeta o âmbito global.
Primeiro, para exibir o $ConfirmPreference
valor da variável no escopo local, use o seguinte comando:
PS> $ConfirmPreference
High
Crie um script Scope.ps1 que contenha os seguintes comandos:
$ConfirmPreference = "Low"
"The value of `$ConfirmPreference is $ConfirmPreference."
Execute o script. O script altera o valor da $ConfirmPreference
variável e, em seguida, relata seu valor no escopo do script. A saída deve ser semelhante à seguinte saída:
The value of $ConfirmPreference is Low.
Em seguida, teste o valor atual da $ConfirmPreference
variável no escopo atual.
PS> $ConfirmPreference
High
Este exemplo mostra que as alterações no valor de uma variável no escopo do script não afetam o valor da variável no escopo pai.
Você pode usar modificadores de escopo para exibir o valor de uma variável no escopo local e em um escopo pai.
Primeiro, defina uma $test
variável no âmbito global.
$test = "Global"
Em seguida, crie um Sample.ps1
script que defina a $test
variável. No script, use um modificador de escopo para se referir às versões global ou local da $test
variável.
Em Sample.ps1
:
$test = "Local"
"The local value of `$test is $test."
"The global value of `$test is $global:test."
Quando você executa Sample.ps1
o , a saída deve ser semelhante à seguinte saída:
The local value of $test is Local.
The global value of $test is Global.
Quando o script estiver concluído, somente o valor global de $test
será definido na sessão.
PS> $test
Global
A menos que você proteja um item usando a opção Private ou outro método, você pode exibir e alterar o valor de uma variável em um escopo pai.
Primeiro, defina uma $test
variável no âmbito global.
$test = "Global"
Em seguida, crie um script Sample.ps1 que defina a $test
variável. No script, use um modificador de escopo para se referir às versões global ou local da $test
variável.
Em Sample.ps1:
$global:test = "Local"
"The global value of `$test is $global:test."
Quando o script estiver concluído, o valor global de $test
será alterado.
PS> $test
Local
Uma variável pode ser tornada privada usando o modificador de private:
escopo ou criando a variável com a propriedade Option definida como Private
. As variáveis privadas só podem ser visualizadas ou alteradas no âmbito em que foram criadas.
Neste exemplo, o ScopeExample.ps1
script cria cinco funções. A primeira função chama a próxima função, que cria um escopo filho. Uma das funções tem uma variável privada que só pode ser vista no âmbito em que foi criada.
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
A saída mostra o valor da variável em cada escopo. Você pode ver que a variável private só é visível no funcB
, o escopo no qual ela foi criada.
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'
Conforme mostrado pela saída do ShowScopes
, você pode acessar variáveis de outros escopos usando Get-Variable
e especificando um número de escopo.
Para variáveis em um comando remoto criado na sessão local, use o modificador de using
escopo. O PowerShell pressupõe que as variáveis nos comandos remotos foram criadas na sessão remota.
A sintaxe é:
$using:<VariableName>
Por exemplo, os comandos a seguir criam uma $Cred
variável na sessão local e, em seguida, usam a $Cred
variável em um comando remoto:
$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $using:Cred}
O using
modificador de escopo foi introduzido no PowerShell 3.0.
Comentários do PowerShell
O PowerShell é um projeto código aberto. Selecione um link para fornecer comentários: