Reinicialização automática de serviços parados do Windows

Resumo

Foi desenvolvido um script completo em PowerShell capaz de identificar automaticamente serviços do Windows que estão parados, mas configurados para inicialização automática ou manual, tentando reiniciá-los com até três tentativas. O script protege serviços críticos do sistema, gera log detalhado com cores no console e arquivo, além de exibir resumo visual ao final da execução. Ideal para manutenção preventiva em estações de trabalho e servidores.

Introdução

Em ambientes Windows, é comum serviços essenciais parem inesperadamente devido a falhas de memória, atualizações do sistema, conflitos de software ou reinicializações incompletas. Quando isso ocorre, o usuário percebe sintomas como impressoras que desaparecem, áudio sem funcionar, conexão de rede instável ou lentidão geral do sistema.

Verificar e reiniciar serviços manualmente via services.msc é inviável em larga escala e exige conhecimento técnico. Este script automatiza todo o processo de forma segura, rápida e auditável, tornando-se uma ferramenta indispensável para técnicos de suporte, administradores de TI e até usuários avançados.

Contexto de execução – Quando e onde usar este script

Este script é extremamente útil nos seguintes cenários:

  • Execução automática após reboot do servidor ou estação (via GPO ou Task Scheduler).
  • Tarefa agendada diária/noturna em servidores críticos (SQL, AD, Exchange, File Server, etc.)
  • Pós-atualização do Windows (muitas vezes o Windows Update para serviços e não reinicia).
  • Ambientes com falhas frequentes no Windows Defender, Firewall ou outros serviços de segurança.
  • Diagnóstico rápido em estações de usuários que apresentam comportamento estranho.
  • Substituição de soluções comerciais caras de monitoramento de serviços.

O que o script NÃO faz

Ele não altera serviços críticos do Windows, se tentar iniciar o “BFE” (Base Filtering Engine) ou “WinDefend” à força, você pode derrubar a máquina. O script simplesmente ignora esses serviços.

Configuração inicial e criação da pasta de log

PowerShell
# Define onde os logs serão salvos (na área de trabalho do usuário)
$PastaLog = "$env:USERPROFILE\Desktop\LogsServicos"

# Cria um nome de arquivo com data e hora para não sobrescrever logs antigos
$DataHora = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$LogPath = "$PastaLog\ServicosReinicioParados_$DataHora.log"

# Quantas vezes o script vai tentar iniciar um serviço
$MaxTentativas = 3

Fonte elaborada pelo autor.

Cria a pasta LogsServicos na área de trabalho do usuário e define o nome do log com data e hora para nunca sobrescrever, além de define que cada serviço terá no máximo 3 tentativas para reiniciar.

PowerShell
# Lista de serviços CRÍTICOS do Windows que NUNCA devem ser reiniciados automaticamente
# (são serviços de segurança, firewall, perfil de usuário, etc.)
$ServicosCriticos = @(
    "BFE","EventLog","MpsSvc","WinDefend","wscsvc","Sense","SecurityHealthService",
    "McpManagementService","WdNisSvc","DPS","Wcmsvc","VaultSvc","TokenBroker",
    "NetSetupSvc","SENS","SystemEventsBroker", "TimeBrokerSvc", "Schedule", 
    "ProfSvc", "UserManager"
)

Fonte elaborada pelo autor.

Uma lista com 21 serviços que nunca serão reiniciados automaticamente. Se forem reiniciados automaticamente podem causar tela azul, perda de login ou desativação da proteção em tempo real. São intencionalmente ignorados.

PowerShell
# Função para escrever no log e também mostrar na tela com cores
function Write-Log {
    param([string]$Mensagem,[ValidateSet("INFO","WARN","ERROR","SUCCESS")]$Nivel="INFO")
    $cores = @{ INFO="White"; WARN="Yellow"; ERROR="Red"; SUCCESS="Green" }
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Nivel] $Mensagem`r`n"
    try {
        # Grava no arquivo
        $utf8Bom = New-Object System.Text.UTF8Encoding $true
        [IO.File]::AppendAllText($LogPath, $logEntry, $utf8Bom)
        Write-Host $logEntry.Trim() -ForegroundColor $cores[$Nivel]
    } catch {
        Write-Host "Falha ao gravar no log: $($_.Exception.Message)" -ForegroundColor Red
    }
}

Fonte elaborada pelo autor.

Função que gera o log e exibe no console com cores (verde = sucesso, vermelho = erro, etc.) ao final cria um arquivo de texto automaticamente na pasta criada anteriormente. O tratamento de erro caso a pasta esteja bloqueada

PowerShell
# Se a pasta de logs não existir, cria ela
if (-not (Test-Path $PastaLog)) { New-Item -ItemType Directory -Path $PastaLog -Force | Out-Null }

# Cria o arquivo de log vazio
[IO.File]::WriteAllBytes($LogPath, [byte[]]@(0xEF,0xBB,0xBF))

Fonte elaborada pelo autor.

Responsável pela criação automática do diretório de logs, caso ele ainda não exista, e pela inicialização do arquivo de log com codificação correta.

PowerShell
# Primeira linha do log
Write-Log "Verificacao iniciada" "INFO"

# Contadores para o resumo final
$reiniciados = 0
$falhas = 0

try {
    # Busca todos os serviços que estão PARADOS mas que NÃO estão desativados (ou seja, deveriam estar rodando)
    $servicos = Get-CimInstance Win32_Service -Property Name,DisplayName,State,StartMode |
                Where-Object { $_.State -eq "Stopped" -and $_.StartMode -ne "Disabled" }
    Write-Log "Encontrados $($servicos.Count) servico(s) parado(s)." "INFO"
} catch {
    # Se der erro ao ler os serviços (raro), avisa e para tudo
    Write-Log "Erro ao ler servicos: $($_.Exception.Message)" "ERROR"
    Write-Host "Erro critico. Consulte o log em $LogPath" -ForegroundColor Red
    pause
    exit 1
}

Fonte elaborada pelo autor.

Armazena a quantidade que foi possível reiniciar e quantos falharam, usando CIM para listar apenas serviços que estão parados, mas não estão desabilitados.

PowerShell
# Loop por cada serviço parado que deveria estar rodando
foreach ($svc in $servicos) {
    # Pula serviços críticos (não mexemos neles para não danificar o Windows Defender, firewall, etc.)
    if ($ServicosCriticos -contains $svc.Name -or $ServicosCriticos -contains $svc.DisplayName) { 
        continue 
    }

    $nome = $svc.DisplayName
    $svcName = $svc.Name
    Write-Log "Iniciando: $nome ($svcName)" "INFO"

    # Tenta iniciar o serviço até 3 vezes
    for ($i = 1; $i -le $MaxTentativas; $i++) {
        try {
            # Tenta iniciar o serviço
            Invoke-CimMethod -InputObject $svc -MethodName StartService -ErrorAction Stop | Out-Null
            Write-Log "Sucesso: $nome ($svcName)" "SUCCESS"
            $reiniciados++    # conta como sucesso
            break             # sai do loop de tentativas
        } catch {
            # Se falhou e foi a última tentativa
            if ($i -eq $MaxTentativas) {
                Write-Log "Falha definitiva: $nome ($svcName)" "ERROR"
                $falhas++     # conta como falha
            } else {
                # Se ainda tem tentativas, espera 5 segundos antes de tentar de novo
                Start-Sleep -Seconds 5
            }
        }
    }
}

Fonte elaborada pelo autor.

Para cada serviço encontrado tenta iniciar até 3 vezes (com 5 segundos de espera entre tentativas) e registra sucesso ou falha definitiva. Ignora se estiver na lista de serviços críticos

PowerShell
Write-Log "VERIFICACAO CONCLUIDA" "INFO"

# Mostra onde o log foi salvo
Write-Host "`nLog salvo em:" -ForegroundColor Cyan
Write-Host " $LogPath`n" -ForegroundColor White

# Mensagem de fechamento com contagem regressiva de 10 segundos
Write-Host "Pressione qualquer tecla para fechar ou aguarde 10 segundos..." -ForegroundColor Yellow

$timeout = 10
$host.UI.RawUI.FlushInputBuffer()
while ($timeout -gt 0 -and -not [Console]::KeyAvailable) {
    Write-Host " Fechando em $timeout segundo(s)... `r" -NoNewline -ForegroundColor DarkGray
    Start-Sleep -Seconds 1
    $timeout--
}
if ([Console]::KeyAvailable) { $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") }

Write-Host "`nJanela fechada." -ForegroundColor Gray
exit

Fonte elaborada pelo autor.

Mostra quantos serviços foram reiniciados e quantos falharam. Se nada foi encontrado, exibe “Tudo OK”. Mostra exatamente onde o log foi salvo, e aguarda 10 segundos ou uma tecla para fechar.

Com apenas algumas linhas, este script substitui ferramentas comerciais de monitoramento de serviços, reduz drasticamente o tempo de resolução de incidentes relacionados a serviços parados e ainda gera evidência (log com data/hora).

É uma solução simples, segura, gratuita e extremamente eficaz que pode ser implantada em massa em ambientes corporativos, help desks e até em computadores domésticos problemáticos. O resultado final é um Windows mais estável e com menos chamados repetitivos.

Scrip Completo

PowerShell
# Define onde os logs serão salvos (na área de trabalho do usuário)
$PastaLog = "$env:USERPROFILE\Desktop\LogsServicos"

# Cria um nome de arquivo com data e hora para não sobrescrever logs antigos
$DataHora = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$LogPath = "$PastaLog\ServicosReinicioParados_$DataHora.log"

# Quantas vezes o script vai tentar iniciar um serviço
$MaxTentativas = 3

# Lista de serviços CRÍTICOS do Windows que NUNCA devem ser reiniciados automaticamente
# (são serviços de segurança, firewall, perfil de usuário, etc.)
$ServicosCriticos = @(
    "BFE","EventLog","MpsSvc","WinDefend","wscsvc","Sense","SecurityHealthService",
    "McpManagementService","WdNisSvc","DPS","Wcmsvc","VaultSvc","TokenBroker",
    "NetSetupSvc","SENS","SystemEventsBroker", "TimeBrokerSvc", "Schedule", 
    "ProfSvc", "UserManager"
)

# Função para escrever no log e também mostrar na tela com cores
function Write-Log {
    param([string]$Mensagem,[ValidateSet("INFO","WARN","ERROR","SUCCESS")]$Nivel="INFO")
    $cores = @{ INFO="White"; WARN="Yellow"; ERROR="Red"; SUCCESS="Green" }
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Nivel] $Mensagem`r`n"
    try {
        # Grava no arquivo
        $utf8Bom = New-Object System.Text.UTF8Encoding $true
        [IO.File]::AppendAllText($LogPath, $logEntry, $utf8Bom)
        Write-Host $logEntry.Trim() -ForegroundColor $cores[$Nivel]
    } catch {
        Write-Host "Falha ao gravar no log: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# Se a pasta de logs não existir, cria ela
if (-not (Test-Path $PastaLog)) { New-Item -ItemType Directory -Path $PastaLog -Force | Out-Null }

# Cria o arquivo de log vazio
[IO.File]::WriteAllBytes($LogPath, [byte[]]@(0xEF,0xBB,0xBF))

# Primeira linha do log
Write-Log "Verificacao iniciada" "INFO"

# Contadores para o resumo final
$reiniciados = 0
$falhas = 0

try {
    # Busca todos os serviços que estão PARADOS mas que NÃO estão desativados (ou seja, deveriam estar rodando)
    $servicos = Get-CimInstance Win32_Service -Property Name,DisplayName,State,StartMode |
                Where-Object { $_.State -eq "Stopped" -and $_.StartMode -ne "Disabled" }
    Write-Log "Encontrados $($servicos.Count) servico(s) parado(s)." "INFO"
} catch {
    # Se der erro ao ler os serviços (raro), avisa e para tudo
    Write-Log "Erro ao ler servicos: $($_.Exception.Message)" "ERROR"
    Write-Host "Erro critico. Consulte o log em $LogPath" -ForegroundColor Red
    pause
    exit 1
}

# Loop por cada serviço parado que deveria estar rodando
foreach ($svc in $servicos) {
    # Pula serviços críticos (não mexemos neles para não danificar o Windows Defender, firewall, etc.)
    if ($ServicosCriticos -contains $svc.Name -or $ServicosCriticos -contains $svc.DisplayName) { 
        continue 
    }

    $nome = $svc.DisplayName
    $svcName = $svc.Name
    Write-Log "Iniciando: $nome ($svcName)" "INFO"

    # Tenta iniciar o serviço até 3 vezes
    for ($i = 1; $i -le $MaxTentativas; $i++) {
        try {
            # Tenta iniciar o serviço
            Invoke-CimMethod -InputObject $svc -MethodName StartService -ErrorAction Stop | Out-Null
            Write-Log "Sucesso: $nome ($svcName)" "SUCCESS"
            $reiniciados++    # conta como sucesso
            break             # sai do loop de tentativas
        } catch {
            # Se falhou e foi a última tentativa
            if ($i -eq $MaxTentativas) {
                Write-Log "Falha definitiva: $nome ($svcName)" "ERROR"
                $falhas++     # conta como falha
            } else {
                # Se ainda tem tentativas, espera 5 segundos antes de tentar de novo
                Start-Sleep -Seconds 5
            }
        }
    }
}

# Mostra o resumo final
$hora = Get-Date -Format "HH:mm:ss"
if ($reiniciados + $falhas -gt 0) {
    $resumo = "FINALIZADO - $reiniciados iniciado(s) | $falhas falha(s)"
    Write-Host "`n[$hora] $resumo" -ForegroundColor Magenta
    Write-Log $resumo "INFO"
} else {
    Write-Host "`n[$hora] Tudo OK - Nenhum servico precisou ser iniciado." -ForegroundColor Cyan
    Write-Log "Tudo OK - Nenhum servico precisou ser iniciado." "INFO"
}

Write-Log "VERIFICACAO CONCLUIDA" "INFO"

# Mostra onde o log foi salvo
Write-Host "`nLog salvo em:" -ForegroundColor Cyan
Write-Host " $LogPath`n" -ForegroundColor White

# Mensagem de fechamento com contagem regressiva de 10 segundos
Write-Host "Pressione qualquer tecla para fechar ou aguarde 10 segundos..." -ForegroundColor Yellow

$timeout = 10
$host.UI.RawUI.FlushInputBuffer()
while ($timeout -gt 0 -and -not [Console]::KeyAvailable) {
    Write-Host " Fechando em $timeout segundo(s)... `r" -NoNewline -ForegroundColor DarkGray
    Start-Sleep -Seconds 1
    $timeout--
}
if ([Console]::KeyAvailable) { $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") }

Write-Host "`nJanela fechada." -ForegroundColor Gray
exit

Fonte elaborada pelo autor.

About The Author

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *