Gerenciando processos e serviços no Windows via PowerShell

1. Introdução ao gerenciamento de processos e serviços

O PowerShell oferece um conjunto robusto de cmdlets para administrar processos e serviços no Windows. Os dois cmdlets fundamentais são Get-Process e Get-Service, que fornecem acesso direto ao gerenciamento de tarefas do sistema operacional.

Processos representam programas em execução ativa na memória, como navegadores ou editores de texto. Serviços, por outro lado, são aplicações que rodam em background, geralmente iniciadas automaticamente com o sistema, como o Windows Update ou o serviço de impressão.

Para executar comandos de gerenciamento, é necessário abrir o PowerShell como administrador. Isso garante acesso a operações sensíveis como parar serviços críticos ou encerrar processos do sistema.

# Verificando se o PowerShell está em modo administrador
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Write-Host "Executando como administrador: $isAdmin"

2. Listando e inspecionando processos

O cmdlet Get-Process é a ferramenta principal para inspecionar processos. Ele aceita filtros por nome, ID ou módulos carregados.

# Listar todos os processos em execução
Get-Process

# Filtrar por nome específico
Get-Process -Name "chrome"

# Filtrar por ID do processo
Get-Process -Id 1234

# Exibir propriedades avançadas (CPU, memória, handles)
Get-Process | Select-Object Name, Id, CPU, WorkingSet64, HandleCount | Sort-Object CPU -Descending | Format-Table -AutoSize

Para exportar resultados para análise posterior, use o formato CSV:

# Exportar processos com alto consumo de memória para CSV
Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB } | 
    Select-Object Name, Id, CPU, WorkingSet64, StartTime | 
    Export-Csv -Path "C:\Temp\processos_memoria.csv" -NoTypeInformation

3. Gerenciando processos em execução

O PowerShell permite iniciar, parar, suspender e retomar processos com facilidade.

# Iniciar um novo processo
Start-Process -FilePath "notepad.exe" -ArgumentList "C:\Temp\notas.txt"

# Parar um processo específico
Stop-Process -Name "notepad" -Force

# Parar com confirmação antes de encerrar
Get-Process -Name "chrome" | Stop-Process -Confirm

Para suspender e retomar processos, utilizamos a classe Win32_Process via CIM:

# Suspender um processo (pausar)
$process = Get-CimInstance -ClassName Win32_Process -Filter "Name = 'chrome.exe'"
Invoke-CimMethod -InputObject $process -MethodName Suspend

# Retomar um processo suspenso
Invoke-CimMethod -InputObject $process -MethodName Resume

Tratamento de erros é essencial para scripts robustos:

# Parar processo com tratamento de erro
try {
    Get-Process -Name "processo_inexistente" -ErrorAction Stop
} catch {
    Write-Warning "Processo não encontrado: $_"
}

# Parar múltiplos processos com verificação
$processes = Get-Process -Name "chrome", "firefox", "edge" -ErrorAction SilentlyContinue
if ($processes) {
    $processes | Stop-Process -Force
    Write-Host "$($processes.Count) processos encerrados."
} else {
    Write-Host "Nenhum processo encontrado."
}

4. Trabalhando com serviços do Windows

O cmdlet Get-Service gerencia serviços do Windows, incluindo status e tipo de inicialização.

# Listar todos os serviços
Get-Service

# Filtrar por status (Running, Stopped, Paused)
Get-Service | Where-Object { $_.Status -eq 'Running' }

# Exibir tipo de inicialização
Get-Service -Name "Spooler" | Select-Object Name, DisplayName, Status, StartType

Operações básicas em serviços:

# Iniciar serviço
Start-Service -Name "Spooler"

# Parar serviço
Stop-Service -Name "Spooler"

# Pausar serviço
Suspend-Service -Name "Spooler"

# Retomar serviço pausado
Resume-Service -Name "Spooler"

# Reiniciar serviço
Restart-Service -Name "Spooler"

Para alterar o tipo de inicialização, usamos Set-Service:

# Alterar inicialização para Automático
Set-Service -Name "Spooler" -StartupType Automatic

# Alterar para Manual
Set-Service -Name "Spooler" -StartupType Manual

# Desabilitar serviço
Set-Service -Name "Spooler" -StartupType Disabled

5. Automação e scripts avançados

Monitoramento contínuo de processos e serviços com loops:

# Monitorar processo específico a cada 5 segundos
$targetProcess = "notepad"
while ($true) {
    $process = Get-Process -Name $targetProcess -ErrorAction SilentlyContinue
    if (-not $process) {
        Write-Warning "Processo $targetProcess não está em execução!"
        Start-Process -FilePath "notepad.exe"
        Write-Host "Processo reiniciado automaticamente."
    }
    Start-Sleep -Seconds 5
}

Criação de funções personalizadas:

function Get-ProcessHealthReport {
    param(
        [string[]]$ProcessNames,
        [int]$CpuThreshold = 50,
        [int]$MemoryThresholdMB = 200
    )

    $report = @()
    foreach ($name in $ProcessNames) {
        $process = Get-Process -Name $name -ErrorAction SilentlyContinue
        if ($process) {
            $health = @{
                Name = $name
                CPU = [math]::Round($process.CPU, 2)
                MemoryMB = [math]::Round($process.WorkingSet64 / 1MB, 2)
                Status = if ($process.CPU -gt $CpuThreshold -or ($process.WorkingSet64 / 1MB) -gt $MemoryThresholdMB) { "Crítico" } else { "Normal" }
            }
            $report += [PSCustomObject]$health
        }
    }
    return $report
}

# Uso da função
Get-ProcessHealthReport -ProcessNames "chrome", "notepad", "explorer"

Agendamento com Task Scheduler via PowerShell:

# Criar tarefa agendada
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\monitoramento.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00"
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount
Register-ScheduledTask -TaskName "MonitoramentoProcessos" -Action $action -Trigger $trigger -Principal $principal

6. Integração com logs e relatórios

Gravar eventos no Windows Event Log:

# Criar fonte de evento personalizada
New-EventLog -LogName Application -Source "ProcessManager"

# Registrar evento de processo encerrado
$processName = "chrome"
Write-EventLog -LogName Application -Source "ProcessManager" -EventId 1001 -EntryType Information -Message "Processo $processName encerrado manualmente."

Gerar relatórios de saúde do sistema:

# Relatório de processos com alto consumo
$highUsage = Get-Process | Where-Object { $_.CPU -gt 30 -or $_.WorkingSet64 -gt 500MB }
$report = $highUsage | Select-Object Name, Id, CPU, @{N="MemoryMB";E={[math]::Round($_.WorkingSet64/1MB,2)}}, StartTime

# Exportar para HTML
$report | ConvertTo-Html -Title "Relatório de Processos - Alto Consumo" -Head "<style>body { font-family: Arial; } table { border-collapse: collapse; } th, td { border: 1px solid #ddd; padding: 8px; }</style>" | Out-File "C:\Temp\relatorio_processos.html"

# Exportar para CSV
$report | Export-Csv -Path "C:\Temp\relatorio_processos.csv" -NoTypeInformation

7. Solução de problemas e boas práticas

Identificação de serviços travados:

# Encontrar serviços que não respondem
Get-Service | Where-Object { $_.Status -eq 'Running' -and $_.CanPauseAndContinue -eq $false } | 
    ForEach-Object { 
        try {
            $null = Stop-Service -Name $_.Name -Force -ErrorAction Stop
            Start-Service -Name $_.Name
            Write-Host "Serviço $($_.Name) reiniciado com sucesso."
        } catch {
            Write-Warning "Falha ao reiniciar serviço $($_.Name): $_"
        }
    }

Processos zumbis (sem resposta):

# Identificar processos zumbis (que não respondem)
Get-Process | Where-Object { $_.Responding -eq $false } | 
    Select-Object Name, Id, StartTime | 
    Format-Table -AutoSize

# Encerrar processos zumbis
Get-Process | Where-Object { $_.Responding -eq $false } | Stop-Process -Force

Dicas de segurança e auditoria:

# Auditoria de alterações em serviços críticos
$criticalServices = @("Spooler", "W3SVC", "MSSQLSERVER")
$baseline = Get-Service -Name $criticalServices | Select-Object Name, Status, StartType

# Verificar alterações periódicas
$current = Get-Service -Name $criticalServices | Select-Object Name, Status, StartType
Compare-Object -ReferenceObject $baseline -DifferenceObject $current -Property Name, Status, StartType | 
    Where-Object { $_.SideIndicator -eq '=>' } | 
    ForEach-Object { Write-Warning "Alteração detectada no serviço $($_.Name): Status alterado para $($_.Status)" }

Referências