Como os escopos afetam os scripts do PowerShell
Em scripts em lote, as alterações nas variáveis de ambiente têm um impacto global na sessão atual por padrão. Para o PowerShell, o oposto é verdadeiro porque os escopos são usados para isolar as modificações de um script. Aqui, exploraremos como os escopos afetam os scripts do PowerShell e como funcionam em e ao redor deles.
O que é um escopo?
No PowerShell, um “escopo” refere-se ao ambiente atual no qual um script ou shell de comando está operando. Escopos são usados para proteger certos objetos dentro do ambiente de serem modificados involuntariamente por scripts ou funções. Particularmente, as seguintes coisas são protegidas contra modificação por comandos executados em outro escopo, a menos que especificado de outra forma pelos parâmetros nesses comandos:
- Variáveis
- Aliases
- Funções
- Drives PowerShell (PSDrives)
Novos escopos são criados sempre que você executa um script ou função, ou quando você cria uma nova sessão ou instância do PowerShell. Os escopos criados pela execução de scripts e funções têm um relacionamento “pai / filho” com o escopo do qual eles foram criados. Existem alguns escopos que têm significados especiais e podem ser acessados pelo nome:
- o Global escopo é o escopo criado quando o PowerShell é iniciado. Ele inclui as variáveis, aliases, funções e PSDrives que são incorporados ao PowerShell, bem como qualquer um que seja feito pelo seu perfil do PowerShell.
- o Local escopo refere-se a qualquer que seja o escopo atual. Quando você inicia o PowerShell, ele se refere ao escopo Global, dentro de um script, será o escopo do Script, etc..
- o Roteiro O escopo é criado quando um script é executado. Os únicos comandos que operam dentro desse escopo são aqueles que estão no script.
- Privado os escopos podem ser definidos dentro do escopo atual, para evitar que os comandos em outros escopos sejam capazes de ler ou modificar itens aos quais eles poderiam ter acesso.
Os escopos também podem ser referenciados por números em determinados comandos, nos quais o escopo atual é referido como zero e seus ancestrais são referenciados por números inteiros crescentes. Por exemplo, em um script executado no escopo Global, o escopo do script seria 0 e o escopo global seria 1. Um escopo que foi aninhado no escopo do script, como uma função, se referiria ao escopo global como 2 Os números negativos não funcionarão para referenciar escopos de crianças - a razão para isto será evidente em breve..
Como os escopos afetam os comandos
Como mencionado anteriormente, os comandos executados dentro de um escopo não afetarão as coisas em outro escopo, a menos que sejam especificamente instruídos a fazê-lo. Por exemplo, se $ MyVar existir no escopo Global e um script executar um comando para definir $ MyVar como um valor diferente, a versão Global de $ MyVar permanecerá inalterada enquanto uma cópia de $ MyVar é colocada no escopo do Script com o novo valor. Se um $ MyVar não existir, um script irá criá-lo dentro do escopo do Script por padrão - não no escopo Global. É importante lembrar disso enquanto você aprende sobre a relação pai / filho real entre escopos.
O relacionamento pai / filho dos escopos no PowerShell é unidirecional. Os comandos podem ver e, opcionalmente, modificar o escopo atual, seu pai e qualquer escopo acima disso. No entanto, eles não podem ver ou modificar coisas em nenhum filho do escopo atual. Isso ocorre principalmente porque, uma vez que você mudou para um escopo pai, o escopo filho já foi destruído porque cumpriu sua finalidade. Por exemplo, por que você teria que ver ou modificar uma variável no escopo do Script, a partir do escopo Global, depois que o script fosse encerrado? Há muitos casos em que você precisa que as alterações de um script ou de uma função persistam além de sua conclusão, mas não tantas quando você precisa fazer alterações em objetos dentro do escopo do script ou da função antes ou depois de sua execução. (Geralmente, essas coisas serão tratadas como parte do script ou da própria função de qualquer maneira.)
Claro, o que são regras sem exceções? Uma exceção ao acima são os escopos particulares. Objetos nos escopos particulares só podem ser acessados por comandos executados no escopo do qual foram criados. Outra exceção importante são itens que possuem a propriedade AllScope. Essas são variáveis e aliases especiais para os quais uma alteração em qualquer escopo afetará todos os escopos. Os comandos a seguir mostrarão quais variáveis e aliases possuem a propriedade AllScope:
Get-Variable | Where-Object $ _. Options -match 'AllScope' Get-Alias | Where-Object $ _. Opções -match 'AllScope')
Escopos em ação
Para nossa primeira olhada nos escopos em ação, iniciaremos uma sessão do PowerShell em que a variável $ MyVar foi definida como uma string, 'Eu sou uma variável global!', Na linha de comando. Então, o seguinte script será executado a partir de um arquivo chamado Scope-Demo.ps1:
Função FunctionScope 'Alterando $ MyVar com uma função.' $ MyVar = 'Eu fui definido por uma função!' "MyVar diz $ MyVar" "Verificando o valor atual de $ MyVar. ' "MyVar diz $ MyVar" "Alterando $ MyVar por script. ' $ MyVar = 'Eu fui definido por um script!' "MyVar diz $ MyVar" "FunctionScope" Verificando o valor final de MyVar antes da saída do script. ' "MyVar diz $ MyVar" "
Se os scripts do PowerShell funcionassem da mesma maneira que os scripts em lote, esperaríamos que o valor de $ MyVar (ou% MyVar% na sintaxe em lote) mudasse de 'Eu sou uma variável global!' Para 'Eu fui definido por um script'. e, finalmente, para "eu tenho definido por uma função!" onde ficaria até que fosse explicitamente alterado novamente ou a sessão terminada. No entanto, veja o que realmente acontece aqui enquanto nos movemos através de cada um dos escopos - particularmente, depois que a função FunctionScope completou seu trabalho e nós verificamos a variável novamente a partir do Script, e depois o Global, escopo.
Como você pode ver, a variável pareceu mudar à medida que avançávamos no script porque, até que a função FunctionScope fosse concluída, estávamos verificando a variável no mesmo escopo que foi alterado pela última vez. Depois que o FunctionScope foi feito, voltamos para o escopo do Script, onde $ MyVar foi deixado intocado pela função. Então, quando o script terminou, voltamos para o escopo Global, onde ele não tinha sido modificado.
Alcançando Fora do Escopo Local
Portanto, é bom ajudar a evitar a aplicação acidental de alterações no ambiente além de seus scripts e funções, mas e se você realmente quiser fazer essas modificações? Há uma sintaxe especial e bastante simples para criar e modificar objetos além do escopo Local. Basta colocar o nome do escopo no início do nome da variável e colocar dois pontos entre os nomes do escopo e da variável. Como isso:
$ global: MyVar $ script: MyVar $ local: MyVar
Você pode usar esses modificadores ao visualizar e definir variáveis. Vamos ver o que acontece com este script de demonstração:
Função FunctionScope "Alterando $ MyVar no escopo da função local ... '$ local: MyVar =" Este é MyVar no escopo local da função. "' Alterando $ MyVar no escopo do script ... '$ script: MyVar =' MyVar costumava ser definido por um script. Agora definido por uma função. "Alterando $ MyVar no escopo global ... '$ global: MyVar =' MyVar foi definido no escopo global. Agora definido por uma função. "Verificando $ MyVar em cada escopo ... '" Local: $ local: MyVar "" Script: $ script: MyVar "" Global: $ global: MyVar "" "Obtendo o valor atual de $ MyVar.' "MyVar diz $ MyVar" "Alterando $ MyVar por script. ' $ MyVar = 'Eu fui definido por um script!' "MyVar diz $ MyVar" FunctionScope 'Verificando $ MyVar do escopo do script antes de sair.' "MyVar diz $ MyVar" "
Como antes, começaremos definindo a variável no escopo Global e terminaremos com a verificação do resultado final do escopo Global.
Aqui você pode ver que o FunctionScope foi capaz de alterar a variável no escopo do Script, e fazer as alterações persistirem após a conclusão. Além disso, a alteração na variável no escopo Global persistiu mesmo depois que o script foi encerrado. Isso pode ser particularmente útil se você tiver que alterar repetidamente as variáveis dentro de um script ou dentro do escopo Global, usando o mesmo código - basta definir uma função ou script que é escrito para modificar a variável onde e como você precisa dela, e chame isso sempre que essas mudanças forem necessárias.
Como mencionado anteriormente, os números de escopo também podem ser usados em determinados comandos para modificar a variável em diferentes níveis em relação ao escopo Local. Aqui está o mesmo script usado no segundo exemplo acima, mas com a função modificada para usar os comandos Get-Variable e Set-Variable com números de escopo em vez de referenciar diretamente a variável com escopos nomeados:
Função FunctionScope "Alterando $ MyVar no escopo 0, relativo ao FunctionScope ... 'Set-Variable MyVar" Este é MyVar no escopo da função 0. "-Scope 0' Alterando $ MyVar no escopo 1, relativo ao FunctionScope ... 'Set-Variable MyVar 'MyVar foi alterado no escopo 1, de uma função.' -Scope 1 'Alterar $ MyVar no escopo 2, em relação ao Functionscope…' MyVar de Variável de Conjunto 'MyVar foi alterado no escopo 2, a partir de uma função.' -Scope 2 "Verificando $ MyVar em cada escopo ..." Escopo 0: 'Get-Variable MyVar -Scope 0 -ValueOnly' Escopo 1: 'Get-Variable MyVar -Scope 1 -ValueOnly' Escopo 2: 'Get-Variable MyVar -Scope 2 -ValueOnly "" Obtendo o valor atual de $ MyVar. ' "MyVar diz $ MyVar" "Alterando $ MyVar por script. ' $ MyVar = 'Eu fui definido por um script!' "MyVar diz $ MyVar" FunctionScope 'Verificando $ MyVar do escopo do script antes de sair.' "MyVar diz $ MyVar" "
Semelhante a antes, podemos ver aqui como os comandos em um escopo podem modificar objetos em seu escopo pai.
informação adicional
Ainda há muito mais que pode ser feito com escopos do que os que podem caber neste artigo. Os escopos afetam mais do que apenas variáveis, e ainda há mais a ser aprendido sobre escopos particulares e as variáveis AllScope. Para obter informações mais úteis, você pode executar o seguinte comando no PowerShell:
Get-Help about_scopes
O mesmo arquivo de ajuda também está disponível no TechNet.
Crédito da imagem do escopo: spadassin on openclipart