Como automatizar tarefas no Windows com scripts PowerShell

1. Fundamentos da Automação com PowerShell

O PowerShell é uma poderosa ferramenta de automação da Microsoft que combina um shell de linha de comando com uma linguagem de script baseada em .NET. Para começar a automatizar tarefas no Windows, é essencial compreender sua estrutura básica.

Um script PowerShell possui extensão .ps1 e pode conter parâmetros, variáveis e cmdlets. Exemplo de estrutura mínima:

param(
    [string]$Caminho = "C:\Temp"
)

$dataAtual = Get-Date
Write-Host "Executando script em $dataAtual no diretório $Caminho"

As políticas de execução (Execution Policy) controlam quais scripts podem ser executados no sistema. Para liberar a execução de scripts locais, use:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

Cmdlets fundamentais para aprendizado incluem Get-Command (lista comandos disponíveis), Get-Help (documentação) e Get-Member (propriedades e métodos de objetos).

2. Scripts para Gerenciamento de Arquivos e Pastas

A automação de backup é uma das aplicações mais comuns. O script abaixo copia arquivos e compacta:

$origem = "C:\Dados"
$destino = "D:\Backup_$(Get-Date -Format yyyyMMdd).zip"

Copy-Item -Path $origem -Destination "D:\Temp" -Recurse
Compress-Archive -Path "D:\Temp\*" -DestinationPath $destino
Remove-Item -Path "D:\Temp" -Recurse -Force

Para limpeza de disco, removendo arquivos mais antigos que 30 dias:

$limite = (Get-Date).AddDays(-30)
Get-ChildItem -Path "C:\Logs" -Recurse | Where-Object { $_.LastWriteTime -lt $limite } | Remove-Item -Force

Monitoramento de espaço em disco com alerta:

$drive = Get-PSDrive -Name C
if ($drive.Free -lt 10GB) {
    $mensagem = "Espaço em disco C: está abaixo de 10GB. Livre: $([math]::Round($drive.Free/1GB,2)) GB"
    Send-MailMessage -To "admin@empresa.com" -Subject "Alerta de Disco" -Body $mensagem -SmtpServer "smtp.empresa.com"
}

3. Automatizando Tarefas do Sistema Operacional

O Task Scheduler pode ser gerenciado via PowerShell. Para agendar um script:

$acao = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\backup.ps1"
$gatilho = New-ScheduledTaskTrigger -Daily -At "02:00AM"
Register-ScheduledTask -TaskName "BackupDiario" -Action $acao -Trigger $gatilho

Gerenciamento de serviços:

Get-Service -Name "Spooler" | Stop-Service
Start-Service -Name "Spooler"
Restart-Service -Name "Spooler" -Force

Controle de processos travados:

Get-Process -Name "notepad" | Where-Object { $_.CPU -gt 100 } | Stop-Process -Force

4. Manipulação de Logs e Eventos

Leitura de logs do Windows Event Viewer:

Get-WinEvent -LogName System -MaxEvents 100 | Where-Object { $_.LevelDisplayName -eq "Error" }

Criação de log personalizado:

New-EventLog -LogName "MeuApp" -Source "ScriptBackup"
Write-EventLog -LogName "MeuApp" -Source "ScriptBackup" -EntryType Information -EventId 100 -Message "Backup concluído com sucesso"

Exportação de relatório para HTML:

$eventos = Get-WinEvent -LogName Application -MaxEvents 50
$eventos | Select-Object TimeCreated, LevelDisplayName, Message | ConvertTo-Html | Out-File "relatorio.html"

5. Automação de Tarefas de Rede e Internet

Teste de conectividade em múltiplos hosts:

$hosts = @("google.com", "microsoft.com", "servidor.local")
$hosts | ForEach-Object {
    if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
        Write-Host "$_ está online"
    } else {
        Write-Host "$_ está offline"
    }
}

Download automático de arquivos:

$url = "https://exemplo.com/arquivo.zip"
$destino = "C:\Downloads\arquivo.zip"
try {
    Invoke-WebRequest -Uri $url -OutFile $destino -ErrorAction Stop
    Write-Host "Download concluído"
} catch {
    Write-Host "Erro no download: $_"
}

6. Integração com Active Directory e Usuários

Criação de usuários em lote a partir de CSV:

Import-Csv "C:\usuarios.csv" | ForEach-Object {
    New-ADUser -Name $_.Nome -SamAccountName $_.Login -UserPrincipalName "$($_.Login)@dominio.com" -GivenName $_.Nome -Surname $_.Sobrenome -Enabled $true -AccountPassword (ConvertTo-SecureString "Senha123!" -AsPlainText -Force)
}

Relatório de contas inativas:

Search-ADAccount -AccountInactive -TimeSpan 90 -UsersOnly | Select-Object Name, LastLogonDate | Export-Csv "contas_inativas.csv"

7. Boas Práticas e Tratamento de Erros

Uso de Try/Catch para capturar exceções:

try {
    $arquivo = Get-Item "C:\arquivo_inexistente.txt" -ErrorAction Stop
    Remove-Item $arquivo
} catch [System.Management.Automation.ItemNotFoundException] {
    Write-Log "Arquivo não encontrado"
} catch {
    Write-Log "Erro inesperado: $_"
} finally {
    Write-Host "Operação finalizada"
}

Parâmetros robustos com validação:

param(
    [Parameter(Mandatory=$true)]
    [string]$Caminho,

    [ValidateSet("Backup", "Limpeza", "Relatorio")]
    [string]$Tipo = "Backup"
)

Logging com registro de data e hora:

function Write-Log {
    param([string]$Mensagem)
    "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - $Mensagem" | Out-File "C:\Logs\script.log" -Append
}

8. Exemplos Práticos e Próximos Passos

Script completo de backup incremental com compactação:

param(
    [Parameter(Mandatory=$true)]
    [string]$PastaOrigem,
    [Parameter(Mandatory=$true)]
    [string]$PastaDestino,
    [int]$DiasRetencao = 7
)

$data = Get-Date -Format "yyyyMMdd_HHmmss"
$arquivoZip = Join-Path $PastaDestino "backup_$data.zip"

try {
    Compress-Archive -Path "$PastaOrigem\*" -DestinationPath $arquivoZip -CompressionLevel Optimal

    $limite = (Get-Date).AddDays(-$DiasRetencao)
    Get-ChildItem $PastaDestino -Filter "backup_*.zip" | Where-Object { $_.LastWriteTime -lt $limite } | Remove-Item -Force

    Write-EventLog -LogName "Backup" -Source "ScriptBackup" -EntryType Information -EventId 100 -Message "Backup concluído: $arquivoZip"
} catch {
    Write-EventLog -LogName "Backup" -Source "ScriptBackup" -EntryType Error -EventId 200 -Message "Erro: $_"
}

Para versionamento e documentação, utilize comentários no cabeçalho:

<#
.SYNOPSIS
    Script de backup incremental
.DESCRIPTION
    Compacta arquivos de uma pasta de origem e remove backups antigos
.PARAMETER PastaOrigem
    Diretório a ser copiado
.PARAMETER PastaDestino
    Local onde os backups serão armazenados
.PARAMETER DiasRetencao
    Número de dias para manter backups antigos (padrão: 7)
#>

Referências