Para uma melhor experiência com caixas de código, experimente ver o site em um Desktop.
Nos posts anteriores da trilha, digitamos comandos no console e organizamos o código em funções. O próximo passo é guardar tudo isso em um arquivo, um script, para executar quando quiser, agendar ou entregar para um colega.
Neste post, vamos salvar o primeiro script, entender por que o Windows bloqueia a execução na primeira tentativa, passar parâmetros para o script, tratar erros e registrar o que aconteceu em um arquivo de log. No fim, juntamos tudo em um script completo.
Como sempre na trilha, os exemplos foram escritos para o Windows PowerShell 5.1 e só consultam informações; nenhum deles altera o sistema. A exceção é a política de execução, que ajustamos apenas para o seu usuário.
Um script do PowerShell é um arquivo de texto com a extensão .ps1. Crie a pasta C:\Scripts, abra o Windows PowerShell ISE, digite a linha abaixo e salve o arquivo como C:\Scripts\Get-StatusServico.ps1:
# Windows PowerShell 5.1
Get-Service -Name Spooler | Select-Object Name, DisplayName, Status
Para executar, abra o console do PowerShell, entre na pasta e chame o script com .\ na frente do nome:
# Windows PowerShell 5.1
cd C:\Scripts
.\Get-StatusServico.ps1
O .\ é obrigatório. Por segurança, o PowerShell não executa scripts da pasta atual só pelo nome, como o cmd fazia; você precisa indicar o caminho, mesmo que seja a pasta onde já está.
Em um Windows 10 ou 11 recém-instalado, a primeira tentativa costuma falhar com a mensagem "cannot be loaded because running scripts is disabled on this system". Não é erro no script: é a política de execução (execution policy), que no Windows cliente vem como Restricted e não permite rodar nenhum script. No Windows Server, o padrão já é RemoteSigned.
Para ver a política em cada escopo:
# Windows PowerShell 5.1
Get-ExecutionPolicy -List
Para liberar scripts só para o seu usuário, sem precisar de administrador, use RemoteSigned: scripts criados na própria máquina rodam normalmente, e scripts baixados da internet precisam ser assinados digitalmente.
# Windows PowerShell 5.1
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Se um script baixado continuar bloqueado e você confiar na origem, remova a marca de "baixado da internet" com o Unblock-File:
# Windows PowerShell 5.1
Unblock-File -Path C:\Scripts\Get-StatusServico.ps1
Dois avisos importantes. A política de execução não é uma barreira de segurança: ela existe para evitar que alguém rode um script sem querer. E, em ambiente corporativo, ela costuma ser definida por GPO; se o comando acima não tiver efeito, a política vem do domínio e a mudança deve passar pela equipe responsável, não por um contorno.
Um script aceita parâmetros do mesmo jeito que uma função: com um bloco param, que precisa ser a primeira instrução do arquivo. Substitua o conteúdo do Get-StatusServico.ps1 por:
# Windows PowerShell 5.1
param (
[string]$Nome = "Spooler"
)
Get-Service -Name $Nome | Select-Object Name, DisplayName, Status
Agora o mesmo script consulta qualquer serviço:
# Windows PowerShell 5.1
.\Get-StatusServico.ps1 # usa o padrão: Spooler
.\Get-StatusServico.ps1 -Nome wuauserv # Windows Update
Se o serviço não existir, o PowerShell mostra um erro em vermelho e continua para a próxima linha. Em um script, é melhor decidir o que fazer quando algo dá errado. O try tenta executar um bloco, e o catch é executado se houver um erro:
# Windows PowerShell 5.1
try {
Get-Service -Name "ServicoQueNaoExiste" -ErrorAction Stop
}
catch {
Write-Output "Falhou: $($_.Exception.Message)"
}
O detalhe que pega muita gente é o -ErrorAction Stop. Muitos cmdlets tratam o erro como "não fatal": mostram a mensagem e seguem em frente, e aí o catch nunca é acionado. O -ErrorAction Stop transforma o erro em fatal para que o catch o capture. Dentro do catch, $_ representa o erro, e $_.Exception.Message traz só a mensagem.
Um script agendado roda sem ninguém olhando a tela, então ele precisa deixar um registro. A forma mais simples é acrescentar uma linha com data e hora a um arquivo de texto:
# Windows PowerShell 5.1
$log = "$env:TEMP\status-servico.log"
$hora = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $log -Value "$hora Teste de log" -Encoding UTF8
Get-Content -Path $log
O $env:TEMP aponta para a pasta temporária do seu usuário, onde você sempre tem permissão de gravação. O -Encoding UTF8 evita problemas com acentos: sem ele, o Add-Content do PowerShell 5.1 grava com a codificação ANSI do sistema.
Agora o Get-StatusServico.ps1 completo: recebe o nome do serviço, consulta o status, trata o erro e registra o resultado no log e na tela.
# Windows PowerShell 5.1
param (
[string]$Nome = "Spooler"
)
$log = "$env:TEMP\status-servico.log"
function Write-Log {
param ([string]$Mensagem)
$hora = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $log -Value "$hora $Mensagem" -Encoding UTF8
Write-Output $Mensagem
}
try {
$servico = Get-Service -Name $Nome -ErrorAction Stop
Write-Log "Serviço $($servico.DisplayName): $($servico.Status)"
}
catch {
Write-Log "ERRO ao consultar o serviço ${Nome}: $($_.Exception.Message)"
}
Teste com um serviço que existe e com um que não existe, e depois confira o log com Get-Content $env:TEMP\status-servico.log. As duas execuções aparecem registradas, cada uma com a sua hora.
Com isso, você saiu do console para um script de verdade: um arquivo que aceita parâmetros, não quebra no primeiro erro e deixa registro do que fez. É a base dos scripts que usamos no dia a dia da infraestrutura, e é por eles que a trilha continua nos próximos posts.
Esta série tem quatro passos. Se você está começando, siga na ordem:
De comandos a scripts no PowerShell (você está aqui)