Se a sua tarefa no Agendador de Tarefas do Windows começou a falhar de forma intermitente desde janeiro/2024 com o código 0xE0434352, este guia mostra, na prática, como diagnosticar e corrigir o problema rapidamente — com checklists, comandos e exemplos reais para apps .NET (Console).
Visão geral do problema
Uma tarefa diária configurada no Agendador de Tarefas (Task Scheduler) passa a falhar de modo intermitente. Ao executar manualmente o executável, tudo funciona. No histórico da tarefa, o campo Last Run Result exibe 0xE0434352. No Visualizador de Eventos, aparecem entradas de .NET Runtime com Event ID 1026 (e frequentemente um Application Error com Event ID 1000 ao lado).
O que significa o erro 0xE0434352 no .NET
O código 0xE0434352 indica uma exceção do CLR não tratada. Não é a causa em si, mas um container genérico: diz apenas que o seu aplicativo .NET lançou uma exceção que chegou até o topo sem ser capturada. É por isso que, em aplicativos .NET, o 0xE0434352 aparece muito quando algo dá errado fora do seu try/catch
— ou quando o ambiente de execução no Agendador é diferente do ambiente clicando duas vezes no .exe.
Por que falha no Agendador e funciona manualmente
Ao rodar como tarefa, o seu app executa sob outro contexto: usuário (conta de serviço, SYSTEM, outro usuário), diretório de trabalho (padrão: C:\Windows\System32
se “Start in” estiver vazio), variáveis de ambiente, PATH, acessos à rede (mapas de drive não existem), perfis de usuário e até bitness (32/64 bits) podem mudar. Pequenas diferenças aí explicam a maioria dos 0xE0434352 no Task Scheduler.
Causas mais comuns (e como reconhecer)
- Diretório de trabalho ausente: “Start in” vazio; caminhos relativos quebram. Sintoma: FileNotFoundException, logs indo parar em
C:\Windows\System32
, Access denied inesperado. - PATH/variáveis diferentes: bibliotecas nativas (DLL), ferramentas e runtimes não achados quando a tarefa executa.
- Mapeamentos de rede: letras de drive (X:, Z:) não existem em sessão de serviço. Use UNC (
\\servidor\pasta
). Sintoma: DirectoryNotFoundException, IOException, Access denied. - Conta/permissões: a conta configurada não tem acesso a arquivos, shares SMB, banco, certificados, chaves de registro ou precisa de Run with highest privileges.
- Runtime .NET incompatível: app framework-dependent sem o runtime correspondente; após atualizações, o runtime foi alterado/corrompido.
- Intermitência externa: banco de dados, API, fila, antivírus/backup bloqueando arquivos, janelas de manutenção, timeouts.
- Diferenças 32/64 bits e redirecionamentos: acesso a
System32
por app 32 bits vai paraSysWOW64
; leitura/escrita no registro é redirecionada (Wow6432Node
). - Perfil de usuário/certificados: tarefas marcadas como “Do not store password” não acessam rede e podem não carregar o perfil. Certificados em CurrentUser ficam invisíveis.
Checklist de correção (ordem prática)
- Ação e diretório de trabalho
- Programa/script: caminho completo do
.exe
(oucmd.exe
para redirecionar logs). - Start in: pasta do executável.
- Troque caminhos relativos por absolutos em argumentos e configs.
- Programa/script: caminho completo do
- Conta e privilégios
- Marque Run whether user is logged on or not e Run with highest privileges.
- Garanta acesso a pastas, shares (use UNC), banco, certificados e registro.
- Evite “Do not store password” se precisar de rede.
- Bitness e executável correto
- Se o app é 32 bits, acione o
.exe
32 bits; idem para 64 bits. Evite chamar viaSystem32
se não for necessário.
- Se o app é 32 bits, acione o
- Runtime .NET
- .NET Framework: confirme que a versão alvo (ex.: 4.7.2/4.8) está instalada.
- .NET 5+: apps framework-dependent exigem o runtime compatível; alternativamente, publique self-contained.
- Se suspeitar de corrupção após updates, repare/reinstale o runtime.
- Log detalhado para obter a exceção real
- Redirecione
stdout
/stderr
para arquivo (veja exemplos abaixo). - Envolva o
Main
comtry/catch
global e registreex.ToString()
e stack trace. - Confira no Event Viewer os eventos 1026 (.NET Runtime) e 1000 (Application Error) no horário da falha.
- Se necessário, gere crash dumps via WER (LocalDumps).
- Redirecione
- Revisões desde jan/2024
- Liste atualizações aplicadas (.NET/Windows), mudanças de permissões, antivírus, caminhos de rede, políticas de segurança das dependências externas.
- Resiliência e operação
- Configure tentativas (Settings > If the task fails, restart every…) e limite de duração.
- Ative All Tasks History no Agendador para ter histórico detalhado.
Modelo de configuração da tarefa (exemplo)
Guia | Campo | Valor recomendado | Observação |
---|---|---|---|
General | Security options | Run whether user is logged on or not; Run with highest privileges | Evita problemas de UAC e desktop interativo. |
General | Do not store password | Desmarcado (se usar rede) | Sem isso, a tarefa não acessa shares. |
Actions | Program/script | C:\Apps\MeuApp\MeuApp.exe | Evite chamar via cmd sem necessidade. |
Actions | Start in | C:\Apps\MeuApp | Obrigatório para resolver caminhos relativos. |
Triggers | Start | Diário 02:00 | Avalie DST; considere “delay” se a rede sobe depois do boot. |
Conditions | Start only if network available | Habilitado (se depender de rede) | Evita exceções quando a rede está fora. |
Settings | If task fails, restart every | 5 minutes, up to 3 times | Resiliência contra indisponibilidades breves. |
Capturando a exceção real (stdout/stderr e Event Viewer)
A maneira mais rápida de sair do 0xE0434352 genérico é registrar stdout e stderr em arquivo quando a tarefa executa. Defina a ação assim:
Opção A — usar cmd.exe
com redirecionamento
Program/script:
C:\Windows\System32\cmd.exe
Adicionar argumentos (exemplo robusto com data sem caracteres inválidos):
/c powershell -NoProfile -Command ^
"$d = Get-Date -Format 'yyyy-MM-dd_HHmmss'; ^
& 'C:\Apps\MeuApp\MeuApp.exe' *>> 'C:\Logs\MeuApp_' + $d + '.log' 2>&1"
Start in:
C:\Apps\MeuApp
Observações:
%DATE%
pode conter “/” dependendo da localidade — evite em nomes de arquivo.- O operador
*>>
no PowerShell concatenastdout
estderr
no mesmo arquivo (equivalente a2>&1
no CMD).
Opção B — log próprio no código
No Main
, envolva tudo com um try/catch
global e registre a exceção completa. Exemplo para .NET 6+:
using System;
using System.IO;
using System.Threading.Tasks;
internal static class Program
{
public static async Task Main(string\[] args)
{
AppDomain.CurrentDomain.UnhandledException += (s, e) => Log("UnhandledException", e.ExceptionObject as Exception);
TaskScheduler.UnobservedTaskException += (s, e) => { Log("UnobservedTaskException", e.Exception); e.SetObserved(); };```
try
{
Directory.SetCurrentDirectory(AppContext.BaseDirectory); // garante caminhos relativos
await RunAsync(args);
}
catch (Exception ex)
{
Log("MainCatch", ex);
Environment.ExitCode = 1;
}
}
private static Task RunAsync(string[] args)
{
// TODO: seu código
return Task.CompletedTask;
}
private static void Log(string tag, Exception? ex)
{
var logDir = Path.Combine(AppContext.BaseDirectory, "Logs");
Directory.CreateDirectory(logDir);
var file = Path.Combine(logDir, $"MeuApp_{DateTime.Now:yyyy-MM-dd_HHmmss}.log");
File.AppendAllText(file, $"[{DateTime.Now:O}] {tag} :: {ex}\n");
}
```
} </code></pre>
<h2>Habilitando crash dumps (WER LocalDumps)</h2>
<p>Quando a exceção mata o processo antes do seu logger escrever, gere um <em>dump</em> para análise pós-morte:</p>
<pre><code>reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MeuApp.exe" /v DumpFolder /t REGEXPANDSZ /d "C:\Dumps" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MeuApp.exe" /v DumpType /t REG_DWORD /d 2 /f
</code></pre>
<ul>
<li><strong>DumpType 2</strong> = <em>Full</em>. Cria arquivos grandes, mas são os mais úteis.</li>
<li>Crie <code>C:\Dumps</code> e garanta permissão de escrita para a conta da tarefa.</li>
</ul>
<p>Alternativa com ferramenta de captura (exemplo genérico):</p>
<pre><code>procdump -ma -e -x C:\Dumps MeuApp.exe
</code></pre>
<h2>Garantindo o runtime correto</h2>
<h3>.NET Framework (4.x)</h3>
<ul>
<li>Confirme a versão alvo (<em>Target framework</em>) do projeto.</li>
<li>Verifique a instalação no servidor (Painel de Controle > Programas) ou consulte via registro:
<pre><code>reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v Release
Se necessário, execute um reparo da versão correspondente.
.NET 5+ / 6 / 7 / 8
- Se o app for framework-dependent, o runtime exato deve estar presente:
dotnet --info
- Para eliminar a dependência do runtime do sistema, publique como self-contained:
dotnet publish -c Release -r win-x64 --self-contained true ^ /p:PublishSingleFile=true /p:PublishTrimmed=false
Ajustewin-x64
parawin-x86
se preciso.
Rede, permissões e perfis
- Use UNC em vez de letras de drive:
\\servidor\share\pasta\arquivo.txt
- Evite “Do not store password” se precisar de rede. Com essa opção, a tarefa normalmente não autentica em recursos externos.
- ACLs de pastas — garanta leitura/escrita:
icacls "C:\Apps\MeuApp" /grant DOMINIO\svc_meuapp:(OI)(CI)M
- Certificados — se o app usa certificados do usuário, prefira instalá-los em LocalMachine\My ou assegure que o perfil do usuário da tarefa é carregado.
Bitness (32/64 bits), System32 e registro
- Apps 32 bits acessando
C:\Windows\System32
na verdade atingemC:\Windows\SysWOW64
por redirecionamento. Se precisar do System32 real, useC:\Windows\Sysnative
(a partir de processos 32 bits). - Chaves de registro de 32 bits residem sob
HKLM\Software\Wow6432Node
. Verifique o caminho correto.
Diagnóstico rápido (em 10 minutos)
- Preencha Start in e troque todos os caminhos por absolutos.
- Marque Run with highest privileges e execute com a mesma conta que funciona manualmente.
- Redirecione stdout/stderr para um log (PowerShell) e rode a tarefa agora.
- Abra o Event Viewer > Windows Logs > Application e o log gerado — identifique a exceção real (tipo, mensagem, stack).
- Se faltar runtime, instale/repare; se for permissão/rede, ajuste a conta/ACL/UNC; se for intermitência externa, aumente timeout e reconfigure tentativas.
Matriz de sintomas x causas x ações
Sintoma | Causa provável | Ação recomendada |
---|---|---|
0xE0434352, funciona manual | Ambiente diferente (Start in vazio, PATH, conta) | Preencha Start in, use caminhos absolutos, confira conta/privilégios |
FileNotFoundException | Arquivo relativo; log indo para System32 | Usar AppContext.BaseDirectory , diretórios absolutos |
UnauthorizedAccessException | Permissão insuficiente; antivírus bloqueando | ACL adequada; exceção no antivírus para a pasta |
SqlException, timeouts | Banco indisponível no horário | Repetir execução; janelas de manutenção; backoff exponencial |
Não encontra DLL nativa | PATH diferente na tarefa | Adicionar pastas ao PATH da conta/maquina; usar DllImportSearchPath |
Acessos a \\servidor\share falham | “Do not store password” ativo; conta sem direito | Desmarcar opção; conceder direitos; usar conta de domínio |
Falha só em 32 ou 64 bits | Redirecionamentos System32/registro | Chamar executável da bitness correta; usar Sysnative |
Sem logs do app | Crash antes do logger | Ativar LocalDumps; handlers globais de exceção |
Boas práticas para tornar o app “à prova de Agendador”
- Mude o diretório corrente no início:
Directory.SetCurrentDirectory(AppContext.BaseDirectory)
. - Antes de usar arquivos, garanta a existência de pastas (
Directory.CreateDirectory
). - Use caminhos absolutos e logs ricos (com MachineName, usuário,
Environment.CurrentDirectory
,Environment.Is64BitProcess
,Environment.GetEnvironmentVariable("PATH")
). - Aumente timeouts de rede e implemente retry (com jitter).
- Se consumir APIs seguras, valide certificados e armazene chaves no repositório correto (LocalMachine quando rodar sem sessão interativa).
- Mantenha a publicação previsível: self-contained + single file quando desejar imutabilidade do runtime.
Exemplo: log mínimo de ambiente no início do app
Console.WriteLine($"User: {Environment.UserName}");
Console.WriteLine($".NET: {Environment.Version}");
Console.WriteLine($"64-bit process: {Environment.Is64BitProcess}");
Console.WriteLine($"CurrentDirectory: {Environment.CurrentDirectory}");
Console.WriteLine($"BaseDirectory: {AppContext.BaseDirectory}");
Console.WriteLine($"PATH (Machine): {Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine)}");
Executando e inspecionando pelo console
Para disparar a tarefa e ver o resultado sem abrir a GUI:
schtasks /Run /TN "\MinhaPasta\MeuApp_Diario"
timeout /t 5
schtasks /Query /TN "\MinhaPasta\MeuApp_Diario" /V /FO LIST
Revisões desde jan/2024: o que mudou na sua infraestrutura?
- Atualizações do Windows/.NET aplicadas no servidor/desktop.
- Políticas (GPO) afetando permissões, scripts de login, PATH, restrições de execução.
- Segurança: antivírus/EDR aplicando quarentenas ou varreduras no horário da tarefa.
- Dependências: bancos e APIs com novas exigências (TLS, ciphers, certificados intermediários).
- Rede: mudanças em DFS, nomes DNS, roteamento ou credenciais para shares.
Playbook de correção — passo a passo consolidado
- Padronize o ambiente: Start in, caminhos absolutos, conta correta, privilégios elevados.
- Logue tudo: redirecione
stdout/stderr
; inclua contexto do ambiente no início do app. - Identifique a exceção real no Event Viewer e nos logs (tipo, mensagem, stack). O 0xE0434352 é consequência.
- Corrija a causa: ajuste permissões/UNC/timeouts/runtime conforme a exceção.
- Endureça a operação: retentativas e limites; histórico habilitado; monitoramento para alertar próximas falhas.
FAQ rápido
O que exatamente é o Event ID 1026?
É um evento de .NET Runtime que registra uma exceção não tratada. Ele contém o tipo da exceção, mensagem e stack trace — procure-o no mesmo horário da falha da tarefa.
Por que minha letra de drive (Z:) some na tarefa?
Drives mapeados são específicos da sessão. Tarefas em segundo plano não veem esses mapeamentos. Use caminhos UNC (\\servidor\share
).
Rodar como SYSTEM ajuda?
Às vezes simplifica permissões locais, mas não resolve acesso a rede (SYSTEM não autentica em recursos remotos). Prefira uma conta de domínio com os acessos certos.
Publicar self-contained aumenta o tamanho. Vale a pena?
Sim, quando você quer impedir que o runtime do sistema afete seu app. O trade-off é espaço em disco, mas você ganha previsibilidade.
Conclusão
O código 0xE0434352 aponta para uma exceção .NET não tratada — não é a causa raiz. Em tarefas do Agendador, quase sempre há diferença de ambiente, permissão ou runtime entre o modo agendado e o modo manual. Ao padronizar o ambiente (especialmente o Start in), capturar logs/dumps e revisar as dependências externas, você encontra a exceção real e corrige a origem da falha. Com as boas práticas deste guia, suas tarefas .NET voltam a rodar de forma confiável.
Resumo prático: o 0xE0434352 é consequência; a causa real aparece nos logs/dumps. Corrija diferenças de ambiente (diretório de trabalho, PATH, conta, UNC), garanta o runtime correto e trate intermitências externas com retentativas.