Olá pessoal, espero encontrá-los bem!
Algumas vezes podemos nos deparar com cenários em que precisamos tomar uma decisão baseado em um resultado obtido. Por exemplo, imagine que você necessite executar um script de hora em hora para verificar o status de execução de um serviço no Windows. Se ele estiver em execução, nenhuma ação é necessária; se estiver parado, precisa ser reiniciado; se estiver desativado, precisa ser ativado e iniciado.
Possivelmente você deve estar pensando que poderia resolver este problema simplesmente utilizando If, ElseIf e Else, e tomar ações baseado na informação retornada do cmdlet Get-Service, certo?
Sim! Você está correto e esta é uma possibilidade de resolver este problema. Observem o script abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$windowsupdate = Get-Service wuauserv If($windowsupdate.StartType -eq "Disabled"){ Set-Service wuauserv -StartupType Automatic -ErrorVariable WUED Start-Service wuauserv -ErrorVariable WUED If(!$WUED){Write-Host -ForegroundColor Green "O serviço do Windows Update foi habilitado e iniciado." } Else{ Write-Host -ForegroundColor Red $WUED } } ElseIf($windowsupdate.Status -eq "Stopped"){ Start-Service wuauserv -ErrorVariable WUES If(!$WUES){ Write-Host -ForegroundColor Green "O serviço do Windows Update foi iniciado." } Else{ Write-Host -ForegroundColor Red $WUES } } Else{ Write-Host -ForegroundColor Green "O serviço do Windows Update já está em execução. Nenhuma operação foi realizada." } |
Neste exemplo, consegui atender ao cenário proposto onde garanti uma correção ao status de execução do serviço do Windows Update caso ele esteja desativado ou parado. Agora seria necessário apenas criar uma tarefa agendada para a execução ocorrer conforme a necessidade ou utilizar alguma ferramenta de gerenciamento de Desktops ou Servers para realizar a execução de forma controlada.
Então qual é o ponto?
Existe uma outra forma bem interessante em que podemos estruturar um script para tomar diversas ações baseadas em condições a partir de um valor inicial utilizando o operador Switch.
Switch
O operador Switch verifica se um item ou valor inicial atende a uma ou mais condições e executa instruções se as condições forem atendidas.
Sintaxe:
Switch (<item avaliado ou valor inicial>) {
<condição-1> {<instrução se a condição for verdadeira>}
<condição-N> {<instrução se a condição for verdadeira>}
Default {<instrução padrão a ser executada caso nenhuma condição for atendida>} (Opcional)
}
Exemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$numeros = 1..10 $numero = Get-Random $numeros Switch($numero){ 1 {Write-Host -ForegroundColor Green "O número sorteado foi: 1"} 2 {Write-Host -ForegroundColor Green "O número sorteado foi: 2"} 3 {Write-Host -ForegroundColor Green "O número sorteado foi: 3"} 4 {Write-Host -ForegroundColor Green "O número sorteado foi: 4"} 5 {Write-Host -ForegroundColor Green "O número sorteado foi: 5"} 6 {Write-Host -ForegroundColor Green "O número sorteado foi: 6"} 7 {Write-Host -ForegroundColor Green "O número sorteado foi: 7"} 8 {Write-Host -ForegroundColor Green "O número sorteado foi: 8"} 9 {Write-Host -ForegroundColor Green "O número sorteado foi: 9"} 10 {Write-Host -ForegroundColor Green "O número sorteado foi: 10"} } |
1 2 |
PS C:\Users\RobotChicken> .\Sort-Numbers.ps1 O número sorteado foi: 5 |
Como podemos observar no exemplo acima, utilizei uma variável para criar uma lista de números de 1 a 10 e o cmdlet Get-Random para sortear um destes números armazenando na variável $numero. Em seguida utilizei o Switch para verificar cada condição declarada que se atendida, escreve no host da console do Powershell qual número foi o sorteado. Como não declarei a instrução Default (padrão), se nenhuma condição declarada for atendida, nenhuma instrução será executada.
Agora, e se aplicarmos a instrução Default e nenhuma condição for atendida? Observe o exemplo abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$numeros = 1..10 $numero = Get-Random $numeros Switch($numero){ 11 {Write-Host -ForegroundColor Green "O número sorteado foi: 11"} 12 {Write-Host -ForegroundColor Green "O número sorteado foi: 12"} 13 {Write-Host -ForegroundColor Green "O número sorteado foi: 13"} 14 {Write-Host -ForegroundColor Green "O número sorteado foi: 14"} 15 {Write-Host -ForegroundColor Green "O número sorteado foi: 15"} 16 {Write-Host -ForegroundColor Green "O número sorteado foi: 16"} 17 {Write-Host -ForegroundColor Green "O número sorteado foi: 17"} 18 {Write-Host -ForegroundColor Green "O número sorteado foi: 18"} 19 {Write-Host -ForegroundColor Green "O número sorteado foi: 19"} 20 {Write-Host -ForegroundColor Green "O número sorteado foi: 20"} Default {Write-Host -ForegroundColor Green "O número sorteado foi: $numero"} } |
1 2 |
PS C:\Users\RobotChicken> .\Sort-NumbersDefault.ps1 O número sorteado foi: 3 |
Neste exemplo, novamente declaramos uma array de números de 1 a 10 e os selecionamos de forma randômica, contudo, as condições impostas não atendem ao valor inicial. Ao executar o script, foi exibido no host da console que o número 3 foi sorteado. Isto ocorreu porque declaramos uma condição Default (padrão) que simplesmente escreve o texto, juntamente com o número sorteado que está armazenado na variável $numero.
Parâmetros disponíveis para o Switch
-CaseSensitive
Este parâmetro apenas funciona com condições cujos valores são do tipo texto (string). Ao utilizá-lo, serão consideradas letras maiúsculas e minúsculas durante a avaliação de uma condição, logo, o valor da condição deve ser exatamente igual ao valor inicial.
Exemplo:
1 2 3 4 5 6 7 8 9 |
Switch -CaseSensitive ("Robot") { "robot" {Write-Host "robot"} "ROBOT" {Write-Host "ROBOT"} "Robot" {Write-Host "Robot"} "RoBoT" {Write-Host "RoBoT"} "rObOt" {Write-Host "rObOt"} } |
1 2 |
PS C:\Users\RobotChicken> .\Switch-CaseSensitive.ps1 Robot |
-Exact
Ao utilizar este parâmetro, para que uma instrução de condição seja executada, o valor da condição deve ser igual ao valor inicial. Ao utilizá-lo, os parâmetros -Wildcard e -Regex serão ignorados.
Exemplo:
1 2 3 4 5 6 7 8 9 |
Switch -Exact ("Robot") { "robot" {Write-Host "robot"} "ROBOT" {Write-Host "ROBOT"} "Robot" {Write-Host "Robot"} "RoBoT" {Write-Host "RoBoT"} "rObOt" {Write-Host "rObOt"} } |
1 2 3 4 5 6 |
PS C:\Users\RobotChicken> .\Switch-Exact.ps1 robot ROBOT Robot RoBoT rObOt |
-File
Permite a inclusão de um arquivo de texto como valor inicial do operador, onde cada linha deste arquivo será avaliada diante as condições impostas. Se especificarmos diversos arquivos a serem avaliados na operação, apenas o último será considerado.
Exemplo:
1 2 3 4 5 6 7 8 9 |
Switch -File "C:\Users\RobotChicken\switch.txt" { "robot" {Write-Host "robot"} "ROBOT" {Write-Host "ROBOT"} "Robot" {Write-Host "Robot"} "RoBoT" {Write-Host "RoBoT"} "rObOt" {Write-Host "rObOt"} } |
1 2 3 4 5 6 |
PS C:\Users\RobotChicken> .\Switch-File.ps1 robot ROBOT Robot RoBoT rObOt |
–Regex
Permite a utilização de expressões regulares para refinar a avaliação do valor da condição. Ao utilizá-lo, os parâmetros -Wildcard e -Exact serão ignorados.
Exemplo:
1 2 3 4 5 6 7 8 9 10 |
Switch -Regex ("robot") { "robot" {Write-Host "robot"} "ROBOT" {Write-Host "ROBOT"} "Robot" {Write-Host "Robot"} "\w" {Write-Host "Robot Regex"} "RoBoT" {Write-Host "RoBoT"} "rObOt" {Write-Host "rObOt"} } |
1 2 3 4 5 6 7 |
PS C:\Users\RobotChicken> .\Switch-Regex.ps1 robot ROBOT Robot Robot Regex RoBoT rObOt |
-Wildcard
Este parâmetro apenas funciona com condições cujos valores são do tipo texto (string). Quando você utiliza o parâmetro -Wildcard, basicamente você está habilitando a consideração do caractere curinga do Powershell (*) na avaliação das condições. Na prática, você adiciona o asterísco em qualquer posição do valor (texto) de alguma condição desejada e caso o valor inicial tenha termos que façam sentido com o valor inicial, a instrução desta condição será executada. Ao utilizá-lo, os parâmetros -Exact e -Regex serão ignorados.
Exemplo:
1 2 3 4 5 6 7 8 9 |
Switch -Wildcard ("robot") { "*bot" {Write-Host "robot"} "R*OT" {Write-Host "ROBOT"} "Ro*" {Write-Host "Robot"} "RoBo*" {Write-Host "RoBoT"} "r*bOt" {Write-Host "rObOt"} } |
1 2 3 4 5 6 |
PS C:\Users\RobotChicken> .\Switch-Wildcard.ps1 robot ROBOT Robot RoBoT rObOt |
Obs: Entraremos em um deep dive de Regex (Regular Expressions) e Wildcard em posts futuros. Fiquem ligados!
Na prática
Agora que já conhecemos bem o operador e seus parâmetros, lembra do cenário que abordamos no início deste post? Vamos observar como podemos utilizar o Switch para realizar as operações necessárias para atender a todos os critérios solicitados.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
$windowsupdate = Get-Service wuauserv Switch($windowsupdate.StartType){ ("Disabled"){Set-Service wuauserv -StartupType Automatic -ErrorVariable WUED Start-Service wuauserv -ErrorVariable WUED If(!$WUED){Write-Host -ForegroundColor Green "O serviço do Windows Update foi habilitado e iniciado." } Else{ Write-Host -ForegroundColor Red $WUED } } ("Automatic"){ Switch($windowsupdate.Status){ ("Running"){Write-Host -ForegroundColor Green "O serviço do Windows Update já está em execução. Nenhuma operação foi realizada." } ("Stopped"){Start-Service wuauserv -ErrorVariable WUES If(!$WUES){ Write-Host -ForegroundColor Green "O serviço do Windows Update foi iniciado." } Else{ Write-Host -ForegroundColor Red $WUES } } } } ("Manual"){Set-Service wuauserv -StartupType Automatic -ErrorVariable WUED Write-Host -ForegroundColor Green "O serviço do Windows Update foi alterado para início Automático." Switch($windowsupdate.Status){ ("Running"){Write-Host -ForegroundColor Green "O serviço do Windows Update já está em execução. Nenhuma operação foi realizada." } ("Stopped"){Start-Service wuauserv -ErrorVariable WUES If(!$WUES){ Write-Host -ForegroundColor Green "O serviço do Windows Update foi iniciado." } Else{ Write-Host -ForegroundColor Red $WUES } } } } } |
1 2 |
PS C:\Users\RobotChicken> .\Check-ServiceSwitch.ps1 O serviço do Windows Update já está em execução. Nenhuma operação foi realizada. |
Se observarem bem, o esforço para codar (ou escrever um código) a solução utilizando o Switch foi um pouco maior do que com If, ElseIf e Else. Ok, eu acabei incrementando uma condição caso o serviço estiver configurado para iniciar manualmente, mas fica aqui a principal dica que posso dar a vocês: Pensem! Pensem muito antes de começar a codar. Desenhem, rabisquem, procurem estruturar um fluxo de como seu script começa e quais são todas as possibilidades de caminhos que serão seguidos para vocês não escreverem linhas de código que poderiam ser substituídas por um comando, operador ou instruções mais simples que reduzam o número de linhas de código. Lembrando, quanto maior for o número de linhas de código, mais complexo fica para realizar o debug de eventuais erros, seja de continuidade ou processamento do script.
Conclusão
Entendemos que o Switch pode ser uma boa alternativa para o If, ElseIf e Else, mas, vale a pena tentar entender qual dos dois te trará o menor esforço administrativo para ser desenvolvido e o que será mais eficiente para o que necessita. Com mais esta pílula de Powershell desbloqueada, fico na torcida para que vocês enriqueçam cada vez mais suas automações!
É isso aí galera, por hoje é só. Até o próximo post!
Dúvidas, sugestões, críticas? Entre em contato aqui!
Gostou? Deixe seu comentário e não se esqueçam de curtir a página do Facebook na barra lateral!