Os logs de eventos do Windows são uma fonte rica de informações sobre o sistema, aplicativos e segurança. Dominar a leitura e análise desses logs é essencial para qualquer profissional de TI que utiliza PowerShell. Nesta aula, você aprenderá a utilizar os cmdlets Get-EventLog e Get-WinEvent, entenderá as diferenças entre eles, e verá como filtrar, analisar e aplicar esse conhecimento em cenários reais.

Enquanto Get-EventLog é um cmdlet mais antigo e simples, Get-WinEvent é a ferramenta moderna e recomendada, oferecendo maior flexibilidade e desempenho. Vamos explorar ambos, mas com ênfase no Get-WinEvent, pois é o futuro da administração de logs.

Get-EventLog e Get-WinEvent

O cmdlet Get-EventLog foi introduzido no Windows PowerShell 1.0 e permite acessar logs de eventos clássicos, como Application, System e Security. Ele é simples de usar, mas limitado: não suporta consultas complexas e não acessa logs de eventos do Windows PowerShell ou logs de aplicativos modernos.

Por outro lado, Get-WinEvent foi introduzido no PowerShell 3.0 e é o cmdlet recomendado. Ele acessa todos os logs de eventos, incluindo os novos logs do Windows, e oferece suporte a consultas XPath, filtros avançados e melhor desempenho. Além disso, Get-WinEvent pode consultar logs em computadores remotos de forma mais eficiente.

Vamos ver exemplos de uso de ambos:

# Usando Get-EventLog (clássico)
Get-EventLog -LogName System -Newest 5

# Usando Get-WinEvent (moderno)
Get-WinEvent -LogName System -MaxEvents 5

Ambos retornam os cinco eventos mais recentes do log System. No entanto, Get-WinEvent retorna objetos do tipo System.Diagnostics.Eventing.Reader.EventLogRecord, que são mais ricos e consistentes. O Get-EventLog retorna objetos System.Diagnostics.EventLogEntry, que são mais simples.

Para listar todos os logs disponíveis, use:

Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsEnabled

Isso é útil para descobrir logs personalizados ou de aplicativos.

Filtragem

A filtragem é uma das operações mais importantes ao trabalhar com logs de eventos. Você pode filtrar por data, nível de severidade, ID do evento, origem, usuário, entre outros. Com Get-WinEvent, você pode usar o parâmetro -FilterHashtable para criar filtros eficientes.

Por exemplo, para buscar eventos de erro no log System dos últimos 7 dias:

$startDate = (Get-Date).AddDays(-7)
Get-WinEvent -FilterHashtable @{ LogName='System'; Level=2; StartTime=$startDate }

O parâmetro -FilterXPath permite consultas mais avançadas, como:

Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624 or EventID=4625) and TimeCreated[timediff(@SystemTime) <= 86400000]]]"

Esse exemplo busca eventos de logon bem-sucedido (4624) e falha (4625) nas últimas 24 horas.

Você também pode filtrar usando o pipeline e cmdlets como Where-Object, mas isso é menos eficiente para grandes volumes. Prefira sempre os filtros nativos.

Para filtrar por múltiplos critérios no -FilterHashtable, você pode usar chaves como Id, ProviderName, StartTime, EndTime, Level etc. Exemplo:

Get-WinEvent -FilterHashtable @{ LogName='Application'; Level=3; ProviderName='.NET Runtime' }

Isso retorna eventos de aviso do provedor .NET Runtime no log Application.

Análise

Depois de obter os eventos, você pode analisá-los de várias maneiras. Uma abordagem comum é agrupar eventos por propriedade, como ID ou nível, para identificar padrões. O cmdlet Group-Object é útil para isso.

$events = Get-WinEvent -LogName System -MaxEvents 1000
$events | Group-Object Id | Sort-Object Count -Descending | Select-Object Count, Name

Isso mostra os IDs de eventos mais frequentes no log System.

Você também pode analisar a distribuição de eventos ao longo do tempo, usando Group-Object com uma data formatada:

$events | Group-Object { $_.TimeCreated.ToString("yyyy-MM-dd") } | Select-Object Name, Count

Para extrair mensagens detalhadas, você pode acessar a propriedade Message:

Get-WinEvent -LogName System -MaxEvents 1 | Select-Object -ExpandProperty Message

Ou formatar a saída como tabela ou lista:

Get-WinEvent -LogName System -MaxEvents 5 | Format-Table TimeCreated, Id, LevelDisplayName, ProviderName

Para exportar eventos para análise em outra ferramenta, você pode usar Export-Csv ou ConvertTo-Json:

Get-WinEvent -LogName Security -MaxEvents 100 | Export-Csv -Path "security_events.csv" -NoTypeInformation

Isso permite abrir os dados em Excel ou outras ferramentas de BI.

Casos de uso

Os logs de eventos são fundamentais para várias tarefas administrativas e de segurança. Aqui estão alguns casos práticos:

  • Monitoramento de segurança: Detectar tentativas de logon falhas (Event ID 4625) ou contas bloqueadas (Event ID 4740).
  • Troubleshooting de aplicativos: Identificar erros recorrentes de um aplicativo específico no log Application.
  • Auditoria de alterações: Rastrear mudanças em políticas de segurança (Event ID 4719) ou instalação de software (Event ID 11707).
  • Monitoramento de desempenho: Verificar eventos de erro de disco (Event ID 7 ou 51) no log System.
  • Automação de relatórios: Gerar relatórios diários de eventos críticos.

Exemplo de script para monitorar falhas de logon:

$startDate = (Get-Date).AddHours(-24)
$failedLogons = Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4625; StartTime=$startDate }
if ($failedLogons.Count -gt 0) {
    Write-Host "Atenção: $($failedLogons.Count) tentativas de logon falhas nas últimas 24 horas."
    $failedLogons | Select-Object TimeCreated, Message
} else {
    Write-Host "Nenhuma tentativa de logon falha nas últimas 24 horas."
}

Outro caso é limpar logs antigos, embora seja necessário cuidado:

# Limpar eventos com mais de 30 dias do log Application
$cutoff = (Get-Date).AddDays(-30)
Get-WinEvent -LogName Application | Where-Object { $_.TimeCreated -lt $cutoff } | Remove-EventLog -LogName Application

Note que Remove-EventLog remove o log inteiro, não eventos individuais. Para limpar eventos, você precisaria usar a API do Windows, mas isso é avançado e raramente necessário.

Boas práticas

  • Sempre use Get-WinEvent em vez de Get-EventLog para novos scripts.
  • Utilize filtros nativos (-FilterHashtable ou -FilterXPath) para consultas em grandes volumes de eventos.
  • Evite usar Where-Object para filtrar eventos em logs grandes, pois é mais lento.
  • Limite a quantidade de eventos retornados com -MaxEvents para evitar sobrecarga.
  • Exporte eventos para análise externa quando precisar de relatórios complexos.
  • Considere a segurança: o log Security pode exigir privilégios elevados para leitura.

Referências

Exercícios

  1. Exercício 1: Liste os 10 eventos mais recentes do log System usando Get-WinEvent e exiba apenas as propriedades TimeCreated, Id e ProviderName.
  2. ✓ Resposta:
    Get-WinEvent -LogName System -MaxEvents 10 | Select-Object TimeCreated, Id, ProviderName
  3. Exercício 2: Filtrar eventos de erro (Level=2) no log Application das últimas 24 horas usando -FilterHashtable.
  4. ✓ Resposta:
    $startDate = (Get-Date).AddHours(-24)
    Get-WinEvent -FilterHashtable @{ LogName='Application'; Level=2; StartTime=$startDate }
  5. Exercício 3: Agrupe os eventos do log System (últimos 500) por ID e mostre os 5 IDs mais frequentes.
  6. ✓ Resposta:
    Get-WinEvent -LogName System -MaxEvents 500 | Group-Object Id | Sort-Object Count -Descending | Select-Object -First 5 Count, Name
  7. Exercício 4: Exporte os eventos de segurança (Security) das últimas 24 horas para um arquivo CSV chamado "security_24h.csv".
  8. ✓ Resposta:
    $startDate = (Get-Date).AddHours(-24)
    Get-WinEvent -FilterHashtable @{ LogName='Security'; StartTime=$startDate } | Export-Csv -Path "security_24h.csv" -NoTypeInformation
  9. Exercício 5: Use Get-WinEvent com -FilterXPath para buscar eventos com ID 4624 ou 4625 no log Security das últimas 7 dias.
  10. ✓ Resposta:
    $startDate = (Get-Date).AddDays(-7)
    Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624 or EventID=4625) and TimeCreated[timediff(@SystemTime) <= 604800000]]]"