about_Scopes
Descrição breve
Explica o conceito de escopo no PowerShell e mostra como definir e alterar o escopo dos elementos.
Descrição longa
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 altere inadvertidamente um item que não deve ser alterado.
Estas são as regras básicas de escopo:
Os escopos podem aninhar. Um escopo externo é chamado de escopo pai. Quaisquer escopos aninhados são escopos filho desse pai.
Um item fica visível no escopo no qual 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 em um escopo fora do escopo atual.
Um item criado dentro de um escopo só pode ser alterado no escopo em que ele foi criado, a menos que você especifique explicitamente um escopo diferente.
Se você criar um item em um escopo e o item compartilhar seu nome com um item em um escopo diferente, o item original poderá estar oculto sob o novo item, mas não será substituído ou alterado.
Escopos do PowerShell
O PowerShell dá suporte aos seguintes escopos:
Global: o escopo que está em vigor quando o PowerShell é iniciado ou quando você cria uma nova sessão ou runspace. Variáveis e funções que estão presentes quando o PowerShell é iniciado foram criadas no escopo global, como variáveis automáticas e variáveis de preferência. As variáveis, os aliases e as funções em seus perfis do PowerShell também são criados no escopo global. O escopo global é o escopo pai raiz em uma sessão.
Local: o escopo atual. O escopo local pode ser o escopo global ou qualquer outro escopo.
Script: o escopo que é criado enquanto um arquivo de script é executado. Somente os comandos no script são executados no escopo do script. Para os comandos em um script, o escopo do script é o escopo local.
Observação
Privado não é um escopo. É uma opção que altera a visibilidade de um item fora do escopo em que o item é definido.
Escopos pai e filho
Você pode criar um novo escopo filho chamando um script ou uma função. O escopo de chamada é o escopo pai. O script ou função chamado é 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.
A menos que você torne explicitamente os itens privados, os itens no escopo pai estarão disponíveis para o escopo filho. No entanto, os itens criados e alterados no escopo filho não afetam o escopo pai, a menos que você especifique explicitamente o escopo ao criar os itens.
Observação
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 que está vinculado ao escopo global. Todo o código do módulo é executado em uma hierarquia específica do módulo de escopos que tem seu próprio escopo raiz.
Herança
Um escopo filho não herda as variáveis, os aliases e as funções do escopo pai. A menos que um item seja privado, o escopo filho pode exibir os itens no escopo pai. Além disso, ele pode alterar os itens especificando explicitamente o escopo pai, mas os itens não fazem parte do escopo filho.
No entanto, um escopo filho é criado com um conjunto de itens. Normalmente, ele inclui todos os aliases que têm a opção AllScope . Essa opção será discutida posteriormente neste artigo. Ele inclui todas as variáveis que têm a opção AllScope , além de algumas variáveis automáticas.
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
Modificadores de escopo
Uma variável, um alias ou um 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 só está visível para o escopo atual.script:
– Especifica que o nome existe no escopo script. O escopo do script é o escopo do arquivo de script ancestral mais próximo ou Global se não houver nenhum arquivo de script ancestral mais próximo.using:
– Usado para acessar variáveis definidas em outro escopo durante a execução de scripts por meio de cmdlets comoStart-Job
eInvoke-Command
.workflow:
– Especifica que o nome existe em um fluxo de trabalho. Observação: não há suporte para fluxos de trabalho no PowerShell v6 e superior.<variable-namespace>
– Um modificador criado por um provedor PSDrive do PowerShell. Por exemplo:Namespace Descrição Alias:
Aliases definidos no escopo atual Env:
Variáveis de ambiente definidas no escopo atual Function:
Funções definidas no escopo atual Variable:
Variáveis definidas no escopo 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 sejam definidos em um script.
Usando modificadores de escopo
Para especificar o escopo de uma nova variável, alias ou função, use um modificador de escopo.
A sintaxe de um modificador de escopo em uma variável é:
$[<scope-modifier>:]<name> = <value>
A sintaxe de 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"
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 $test
seguir refere-se à variável, primeiro no escopo local e, em seguida, no escopo global:
$test
$global:test
O modificador de escopo Using:
Usar é 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 inserir valores de variáveis do escopo da sessão de chamada, para que o código fora da sessão possa acessá-los. Há Using
suporte para o modificador de escopo 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 por meio
Start-ThreadJob
de ouForEach-Object -Parallel
(sessão de thread separada)
Dependendo do contexto, os valores de variáveis inseridas são cópias independentes dos dados no escopo do chamador ou referências a ele. Em sessões remotas e fora do processo, elas são sempre cópias independentes.
Para obter mais informações, consulte about_Remote_Variables.
Em sessões de thread, elas são passadas por referência. Isso significa que é possível modificar variáveis de escopo de chamada em um thread diferente. Modificar variáveis com segurança requer sincronização de thread.
Para obter mais informações, consulte:
Serialização de valores variáveis
Comandos executados remotamente e trabalhos em segundo plano são executados fora do processo. As sessões fora do processo usam serialização e desserialização baseadas em XML para disponibilizar os valores das variáveis entre os limites do processo. O processo de serialização converte objetos em um PSObject que contém as propriedades de objetos originais, mas não seus métodos.
Para um conjunto limitado de tipos, a desserialização reidrata objetos de volta ao tipo original. O objeto reidratado é uma cópia da instância de objeto original. Ele tem as propriedades e os métodos de tipo. 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 de tipo original prefixado com Desserializado, por exemplo, Deserialized.System.Data.DataTable
A opção AllScope
Variáveis e aliases têm uma propriedade Option que pode levar um valor de AllScope. Os itens que têm a propriedade AllScope tornam-se parte de todos os escopos filho criados, embora não sejam herdados retroativamente por 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.
Gerenciando escopo
Vários cmdlets têm um parâmetro Scope que permite obter ou definir itens (criar e alterar) em um escopo específico. Use o seguinte comando 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 .
Observação
Para os cmdlets que usam o parâmetro Scope , você também pode consultar 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. Escopos numerados serão úteis se você tiver criado muitos escopos recursivos.
Usando notação de origem de ponto com escopo
Scripts e funções seguem todas 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.
Porém, você pode adicionar um script ou uma função ao escopo atual usando a notação de origem de ponto. Em seguida, quando um script é executado no escopo atual, todas as funções, aliases e variáveis que o script cria estão disponíveis no escopo atual.
Para adicionar uma função ao escopo atual, digite um ponto (.) e um espaço antes do caminho e do nome da função na chamada de função.
Por exemplo, para executar o script Sample.ps1 do diretório C:\Scripts no escopo do script (o padrão para scripts), use o seguinte comando:
c:\scripts\sample.ps1
Para executar o script Sample.ps1 no escopo local, use o seguinte comando:
. c:\scripts.sample.ps1
Quando você usa o operador de chamada (&) para executar uma função ou script, ele não é adicionado ao escopo atual. O exemplo a seguir usa o operador de chamada:
& c:\scripts.sample.ps1
Você pode ler mais sobre o operador de chamada no about_operators.
Quaisquer aliases, funções ou variáveis que o script Sample.ps1 cria não estão disponíveis no escopo atual.
Restringindo sem escopo
Alguns conceitos do PowerShell são semelhantes ao escopo ou interagem com o escopo. Esses conceitos podem ser confundidos com escopo ou com o comportamento do escopo.
Sessões, módulos e prompts aninhados são ambientes independentes, mas não são escopos filho do escopo global na sessão.
Sessões
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 independente, 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 seu próprio escopo global. Esse escopo é independente do escopo 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.
Módulos
Você pode usar um módulo do PowerShell para compartilhar e fornecer 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 definido explicitamente, os itens em um módulo não podem ser acessados fora do módulo. Portanto, você pode adicionar o módulo à 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 nível superior do estado da sessão atual e não no escopo atual. O estado da sessão atual pode ser um estado de sessão de módulo ou o estado da sessão global. Adicionar um módulo a uma sessão não altera o escopo. Se você estiver no escopo global, os módulos serão carregados no estado da sessão global. Todas as exportações são colocadas nas tabelas globais.
Se você carregar o módulo2 de dentro do módulo1, module2 será carregado no estado da sessão do módulo1 e não no estado da sessão global. Todas as exportações do módulo2 são colocadas na parte superior do estado da sessão module1. Se você usar Import-Module -Scope local
, as exportações serão colocadas no objeto de escopo atual e não no nível superior. Se você estiver em um módulo e usar Import-Module -Scope global
(ou Import-Module -Global
) para carregar outro módulo, esse módulo e suas exportações serão carregados no estado de sessão global, em vez do estado de sessão local do módulo. Esse recurso foi projetado para escrever módulos que manipulam módulos. O módulo WindowsCompatibility faz isso para importar módulos proxy para o estado da sessão global.
Dentro do estado 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 a ela um valor e chamamos a função foo.
$a = "Goodbye"
foo
O módulo declara a variável $a
no escopo do módulo e, em seguida, a função foo gera o valor da variável em ambos os escopos.
$a = Hello
$global:a = Goodbye
Prompts aninhados
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 chegar a um ponto de interrupção no script, insira o escopo do script.
Opção privada
Aliases e variáveis têm uma propriedade Option que pode levar um valor de Private. Os itens que têm a opção Private podem ser exibidos e alterados no escopo no qual são criados, mas não podem ser exibidos ou alterados fora desse escopo.
Por exemplo, se você criar uma variável que tenha uma opção privada no escopo global e executar um script, Get-Variable
os comandos no script não exibirão a variável privada. O uso do modificador de escopo global nesta instância não exibe a variável privada.
Você pode usar o parâmetro Option dos New-Variable
cmdlets , Set-Variable
, New-Alias
e Set-Alias
para definir o valor da propriedade Option como Private.
Visibilidade
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, um script ou um snap-in. A visibilidade foi projetada para contêineres da mesma forma que o valor Privado da propriedade Option foi projetado para escopos.
A propriedade Visibility usa os valores Público e Privado . Os itens que têm visibilidade privada podem ser exibidos e alterados somente 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 foi 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.
Exemplos
Exemplo 1: alterar um valor variável somente em um script
O comando a seguir altera o valor da $ConfirmPreference
variável em um script. A alteração não afeta o escopo global.
Primeiro, para exibir o valor da $ConfirmPreference
variável no escopo local, use o seguinte comando:
PS> $ConfirmPreference
High
Create um script Scope.ps1 que contém 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.
Exemplo 2: exibir um valor de variável em escopos diferentes
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 escopo global.
$test = "Global"
Em seguida, crie um script Sample.ps1 que define a $test
variável. No script, use um modificador de escopo para se referir às versões globais ou locais 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, 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 for concluído, somente o valor global de $test
será definido na sessão.
PS> $test
Global
Exemplo 3: alterar o valor de uma variável em um escopo pai
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 escopo global.
$test = "Global"
Em seguida, crie um script Sample.ps1 que define a $test
variável. No script, use um modificador de escopo para se referir às versões globais ou locais da $test
variável.
Em Sample.ps1:
$global:test = "Local"
"The global value of `$test is $global:test."
Quando o script é concluído, o valor global de $test
é alterado.
PS> $test
Local
Exemplo 4: Criando uma variável privada
Uma variável privada é uma variável que tem uma propriedade Option que tem um valor de Private. As variáveis privadas são herdadas pelo escopo filho, mas só podem ser exibidas ou alteradas no escopo em que foram criadas.
O comando a seguir cria uma variável privada chamada $ptest
no escopo local.
New-Variable -Name ptest -Value 1 -Option private
Você pode exibir e alterar o valor de $ptest
no escopo local.
PS> $ptest
1
PS> $ptest = 2
PS> $ptest
2
Em seguida, crie um script Sample.ps1 que contém os comandos a seguir. O comando tenta exibir e alterar o valor de $ptest
.
Em Sample.ps1:
"The value of `$Ptest is $Ptest."
"The value of `$Ptest is $global:Ptest."
A $ptest
variável não está visível no escopo do script, a saída está vazia.
"The value of $Ptest is ."
"The value of $Ptest is ."
Exemplo 5: usando uma variável local em um comando remoto
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 em comandos remotos foram criadas na sessão remota.
A sintaxe do é:
$Using:<VariableName>
Por exemplo, os seguintes comandos criam uma $Cred
variável na sessão local e usam a $Cred
variável em um comando remoto:
$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $Using:Cred}
O escopo Using foi introduzido no PowerShell 3.0. No PowerShell 2.0, para indicar que uma variável foi criada na sessão local, use o seguinte formato de comando.
$Cred = Get-Credential
Invoke-Command $s {
param($c)
Remove-Item .\Test*.ps1 -Credential $c
} -ArgumentList $Cred