Compartilhar via


Capítulo 6 – Controle de fluxo

Criação de scripts

Quando se passa de escrever linhas únicas para scripts do PowerShell, parece mais complicado do que é. Um script nada mais é do que os mesmos comandos ou comandos semelhantes que você executa interativamente no console do PowerShell, com a exceção de que você os salva como um arquivo .ps1. Há algumas construções de script que você pode usar, como um foreach loop em vez do ForEach-Object cmdlet. As diferenças podem ser confusas para iniciantes ao considerar que foreach é uma palavra-chave de linguagem e um alias para o ForEach-Object cmdlet.

Loop

Um dos melhores aspectos do PowerShell é sua escalabilidade. Depois de aprender a executar uma tarefa para um único item, aplicar a mesma ação a centenas de itens é quase tão simples quanto. Percorra os itens usando um dos diferentes tipos de loops no PowerShell.

ForEach-Object

ForEach-Object é um cmdlet para iterar em itens de um pipeline, como é o caso dos comandos de uma linha do PowerShell. ForEach-Object encaminha os objetos pelo pipeline.

Embora o parâmetro do Módulo de Get-Command aceite múltiplos valores de strings, ele só os aceita por meio de entrada de pipeline pelo nome da propriedade. No cenário a seguir, se você quiser redirecionar dois valores de cadeia de caracteres para o Get-Command para uso com o parâmetro Module, será necessário utilizar o cmdlet ForEach-Object.

'ActiveDirectory', 'SQLServer' |
    ForEach-Object {Get-Command -Module $_} |
    Group-Object -Property ModuleName -NoElement |
    Sort-Object -Property Count -Descending
Count Name
----- ----
  147 ActiveDirectory
   82 SqlServer

No exemplo anterior, $_ é o objeto atual. A partir do PowerShell versão 3.0, $PSItem pode ser usado em vez de $_. A maioria dos usuários mais experientes do PowerShell preferem usar $_, já que ele é compatível com as versões anteriores e leva menos tempo para digitar.

Quando usar a palavra-chave foreach, você precisará armazenar todos os itens na memória antes de iterar neles, o que pode ser difícil se você não souber com quantos itens está trabalhando.

$ComputerName = 'DC01', 'WEB01'
foreach ($Computer in $ComputerName) {
    Get-ADComputer -Identity $Computer
}
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com
DNSHostName       : dc01.mikefrobbins.com
Enabled           : True
Name              : DC01
ObjectClass       : computer
ObjectGUID        : c38da20c-a484-469d-ba4c-bab3fb71ae8e
SamAccountName    : DC01$
SID               : S-1-5-21-2989741381-570885089-3319121794-1001
UserPrincipalName :

DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com
DNSHostName       : web01.mikefrobbins.com
Enabled           : True
Name              : WEB01
ObjectClass       : computer
ObjectGUID        : 33aa530e-1e31-40d8-8c78-76a18b673c33
SamAccountName    : WEB01$
SID               : S-1-5-21-2989741381-570885089-3319121794-1107
UserPrincipalName :

Muitas vezes um loop como foreach ou ForEach-Object é necessário. Caso contrário, você receberá uma mensagem de erro.

Get-ADComputer -Identity 'DC01', 'WEB01'
Get-ADComputer : Cannot convert 'System.Object[]' to the type
'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter
'Identity'. Specified method is not supported.
At line:1 char:26
+ Get-ADComputer -Identity 'DC01', 'WEB01'
+                          ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-ADComputer], Parame
   terBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirecto
   ry.Management.Commands.GetADComputer

Outras vezes, você pode obter os mesmos resultados ao eliminar o loop. Consulte a ajuda do cmdlet para entender suas opções.

'DC01', 'WEB01' | Get-ADComputer
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com
DNSHostName       : dc01.mikefrobbins.com
Enabled           : True
Name              : DC01
ObjectClass       : computer
ObjectGUID        : c38da20c-a484-469d-ba4c-bab3fb71ae8e
SamAccountName    : DC01$
SID               : S-1-5-21-2989741381-570885089-3319121794-1001
UserPrincipalName :

DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com
DNSHostName       : web01.mikefrobbins.com
Enabled           : True
Name              : WEB01
ObjectClass       : computer
ObjectGUID        : 33aa530e-1e31-40d8-8c78-76a18b673c33
SamAccountName    : WEB01$
SID               : S-1-5-21-2989741381-570885089-3319121794-1107
UserPrincipalName :

Como você pode ver nos exemplos anteriores, o parâmetro Identity aceita Get-ADComputer apenas um único valor quando fornecido por meio de entrada de parâmetro. No entanto, usando o pipeline, você pode enviar vários valores para o comando porque os valores são processados um de cada vez.

Para

Um loop for itera enquanto uma condição especificada é verdadeira. Eu não uso o for loop com frequência, mas ele tem usos.

for ($i = 1; $i -lt 5; $i++) {
    Write-Output "Sleeping for $i seconds"
    Start-Sleep -Seconds $i
}
Sleeping for 1 seconds
Sleeping for 2 seconds
Sleeping for 3 seconds
Sleeping for 4 seconds

No exemplo anterior, o loop itera quatro vezes começando com o número um e continuando desde que a variável $i de contador seja menor que 5. Ele dorme por um total de 10 segundos.

Fazer

Há dois loops diferentes do no PowerShell: do until e do while. do until é executado enquanto a condição especificada é falsa.

O exemplo a seguir é um jogo de números que continua até que o valor que você adivinha seja igual ao mesmo número que o Get-Random cmdlet gerou.

$number = Get-Random -Minimum 1 -Maximum 10
do {
    $guess = Read-Host -Prompt "What's your guess?"
    if ($guess -lt $number) {
        Write-Output 'Too low!'
    } elseif ($guess -gt $number) {
        Write-Output 'Too high!'
    }
}
until ($guess -eq $number)
What's your guess?: 1
Too low!
What's your guess?: 2
Too low!
What's your guess?: 3

Do While faz o oposto. Ele é executado desde que a condição especificada seja avaliada como verdadeira.

$number = Get-Random -Minimum 1 -Maximum 10
do {
    $guess = Read-Host -Prompt "What's your guess?"
    if ($guess -lt $number) {
        Write-Output 'Too low!'
    } elseif ($guess -gt $number) {
        Write-Output 'Too high!'
    }
}
while ($guess -ne $number)
What's your guess?: 1
Too low!
What's your guess?: 2
Too low!
What's your guess?: 3
Too low!
What's your guess?: 4

Os mesmos resultados são obtidos com um loop Do While, revertendo a condição de teste para não é igual a.

do os loops sempre são executados pelo menos uma vez porque a condição é avaliada no final do loop.

Enquanto

Assim como o do while loop, um while loop é executado desde que a condição especificada seja verdadeira. A diferença, no entanto, é que um while loop avalia a condição na parte superior do loop antes que qualquer código seja executado. Portanto, ele não será executado se a condição for avaliada como false.

O exemplo a seguir calcula em que dia é o Dia de Ação de Graças nos Estados Unidos. É sempre na quarta quinta-feira de novembro. O loop começa com o 22º dia de novembro e adiciona um dia, enquanto o dia da semana não é igual a quinta-feira. Se o dia 22 for uma quinta-feira, o loop não será executado.

$date = Get-Date -Date 'November 22'
while ($date.DayOfWeek -ne 'Thursday') {
    $date = $date.AddDays(1)
}
Write-Output $date
Thursday, November 23, 2017 12:00:00 AM

interromper, continuar e retornar

A break palavra-chave foi projetada para sair de um loop e geralmente é usada com a instrução switch . No exemplo a seguir, break faz com que o loop termine após a primeira iteração.

for ($i = 1; $i -lt 5; $i++) {
    Write-Output "Sleeping for $i seconds"
    Start-Sleep -Seconds $i
    break
}
Sleeping for 1 seconds

A continue palavra-chave foi projetada para passar para a próxima iteração de um loop.

O exemplo a seguir gera os números 1, 2, 4 e 5. Ele ignora o número 3 e continua com a próxima iteração do loop. Como break, continue sai do loop, exceto apenas para a iteração atual. A execução continua com a próxima iteração em vez de sair completamente do loop e parar.

while ($i -lt 5) {
    $i += 1
    if ($i -eq 3) {
        continue
    }
    Write-Output $i
}
1
2
4
5

A return palavra-chave foi projetada para sair do escopo existente.

Observe no exemplo a seguir que return gera o primeiro resultado e, em seguida, sai do loop.

$number = 1..10
foreach ($n in $number) {
    if ($n -ge 4) {
        return $n
    }
}
4

Uma explicação mais completa da instrução de resultado pode ser encontrada em um dos meus artigos de blog: a palavra-chave de retorno do PowerShell.

Resumo

Neste capítulo, você aprendeu sobre os diferentes tipos de loops que existem no PowerShell.

Revisão

  1. Qual é a diferença entre o ForEach-Object cmdlet e a instrução foreach ?
  2. Qual é a principal vantagem de usar um while loop em vez de um do while loop ou do until loop?
  3. Como as instruções break e continue diferem?

Referências

Próximas etapas

No Capítulo 7, você aprenderá a recuperar e trabalhar com informações do sistema usando a Instrumentação de Gerenciamento do Windows (WMI) e o CIM (Common Information Model). Você explorará os cmdlets modernos baseados em CIM, entenderá como eles diferem dos comandos herdados do WMI e os usará para consultar sistemas locais e remotos com eficiência.