Windows Server 2025: evita el bloqueo de procesos SYSTEM al usar servicios con UI en DC virtualizados

Si tras promover un nuevo controlador de dominio en Windows Server 2025 alojado en XCP‑ng tus procesos que se ejecutan como SYSTEM (tareas programadas, PsExec, scripts de mantenimiento, etc.) se congelan al detenerse, es muy probable que el origen sea un servicio propio que abre una interfaz gráfica durante OnStart. A continuación encontrarás una guía práctica y exhaustiva para diagnosticar, reproducir y, sobre todo, eliminar definitivamente este bloqueo sin comprometer seguridad, rendimiento ni buenas prácticas de administración de controladores de dominio.

Índice

Resumen de la pregunta

Después de instalar en el DC un servicio de Windows escrito en C# con Autostart, dicho servicio genera un formulario vacío en su evento OnStart. Tras reiniciar el servidor, todo proceso lanzado bajo la identidad NT AUTHORITY\SYSTEM se queda colgado cuando el sistema intenta cerrarlo. El objetivo es averiguar la causa exacta y la forma de evitarlo.

Entorno y síntoma

  • Sistema operativo : Windows Server 2025 Datacenter (versión para SAC) actualizado a la última “Patch Tuesday”.
  • Rol del servidor : Controlador de dominio (nivel funcional 2025).
  • Hipervisor : XCP‑ng 8.3 con drivers paravirtual modernos (PV‑drivers 9.3).
  • Servicio problemático : Binario .NET 8.0 que, durante OnStart, crea ApplicationContext + Form vacío y queda a la espera de eventos.
  • Síntoma : cualquier proceso bajo SYSTEM deja de responder en la fase de “Stopping”, forzando TerminateProcess y generando eventos de error 7022/7036 en el visor.

Causa técnica

Desde Windows Vista los servicios que se ejecutan como SYSTEM quedan aislados en la Sesión 0, mientras que los escritorios interactivos viven en sesiones de usuario (> 1). El servicio, al crear un formulario, intenta inicializar subsistemas de UI (User32, GDI+) que:

  1. Requieren un contexto de ventana asociado a un “desktop” válido.
  2. Bloquean la cola de mensajes de Sesión 0 si no existe un entorno visible.
  3. Impiden la finalización ordenada de otros servicios o procesos que comparten la misma sesión y cuenta SYSTEM, provocando deadlocks en ExitProcess.

En Windows Server 2025 el aislamiento es aún más estricto: políticas de seguridad predeterminadas impiden incluso la suplantación de sesión o la creación de escritorios temporales sin privilegio explícito (SETCBNAME), por lo que el bloqueo se manifiesta de forma inmediata.

Metodología de diagnóstico

AcciónPropósitoResultado esperado
Desplegar el servicio en un servidor miembro físico (no DC)Descartar impacto del rol de controladorBloqueo desaparece ➜ factor DC
Desplegar en DC físicoAislar impacto de la capa de virtualizaciónSi el bloqueo continúa ➜ la virtualización no es la causa
Iniciar el servicio con sc start y parar con sc stopObservar tiempos de paradaVemos espera >30 s → timeout 30 000 ms
Comentarios Form.Show()Confirmar que la UI provoca el deadlockSin UI no hay cuelgue
Monitoreo con procmon + filtros “System”Detectar llamadas bloqueantes (WaitForSingleObjectEx)Handle relacionado con \Sessions\0\BaseNamedObjects\...

Buenas prácticas para diseñar servicios en un DC

Separar lógicas

Divide la solución en dos binarios:

  • Servicio backend sin UI, limitado a la lógica de negocio y expuesto por IPC.
  • Aplicación cliente (WinUI, WPF, MAUI, consola) que se ejecuta bajo un usuario interactivo y se comunica con el servicio.

Canales de comunicación recomendados

  • Named Pipes (rápidas en la misma máquina, ACL integradas).
  • gRPC sobre nPipe o TCP cuando necesitas “streaming” y contratos fuertemente tipados.
  • HTTP(s) local con HttpListener o Kestrel si planeas exponer el servicio a terceros.

Cuenta de servicio

Evita SYSTEM salvo que sea absolutamente necesario. Alternativas:

  • Cuenta administrada de tipo gMSA (Group Managed Service Account) – ideal en entornos con varios DC.
  • Cuenta virtual NT SERVICE\NombreServicio – suficiente para la mayoría de servicios internos.

Recuerda delegar solo los privilegios mínimos (principio de menor privilegio) vía GPO o sc.exe.

Manejo de dependencias

Configura dependencias explícitas con sc config ServicioA depend= ServicioB para asegurar el orden correcto de arranque y parada. Evita dependencias circulares.

Tiempo de espera personalizado

Si el servicio requiere una fase de inicialización larga, ajusta ServicesPipeTimeout en HKLM\SYSTEM\CurrentControlSet\Control (DWORD, milisegundos). No multiplicar el valor por encima de lo razonable (60–90 s) para no enmascarar problemas reales.

Procedimiento paso a paso para la corrección

  1. Extraer la UI del servicio existente
    // Antes protected override void OnStart(string[] args){ Application.Run(new MainForm()); // ❌ } // Después protected override void OnStart(string[] args){ // Lógica sin UI MyEngine.Start(); }
  2. Crear aplicación cliente
    Simple proyecto WinForms/WPF que invoque MyEngine vía gRPC o Pipe.
  3. Registrar el servicio
    sc create MyEngine binPath= “C:\Srv\MyEngine.exe” obj= “NT SERVICE\MyEngine”
  4. Probar parada/arranque varias veces asegurándote de que los eventos 7036 aparecen con duración <1 s.
  5. Instrumentar con ETW si persisten demoras: logman start UIBlock -p Microsoft-Windows-Win32k -ets Analiza con Windows Performance Analyzer.

Notas específicas para XCP‑ng

En entornos paravirtualizados el subsistema de sesiones puede tardar unos milisegundos extra en inicializar durante el arranque, pero no es causa directa del bloqueo. Sin embargo:

  • Comprueba que los PV‑drivers estén actualizados; versiones antiguas (< 8.2) registran hooks Win32k que afectan a Sesión 0.
  • Deshabilita la opción “Wait for tools to respond on shutdown” en la política de energizado de la VM para evitar tiempos de espera fantasma.

Riesgos de seguridad

Presentar una interfaz gráfica desde SYSTEM en un DC:

  • Rompe la superficie de ataque 0 que Microsoft defiende desde Windows Server 2008.
  • Permite shatter attacks, donde un proceso de menor privilegio inyecta mensajes ventana que elevan privilegios.
  • Dificulta aplicar Credential Guard y las protecciones LSASS PPL, pues interpones APIs UI clasicamente vulnerables.

Por ello, la separación UI‑servicio no es solo cuestión de estabilidad sino de seguridad corporativa.

Conclusión

El bloqueo de procesos SYSTEM al detenerse en un controlador de dominio Windows Server 2025 se debe, en la mayoría de los casos, a que un servicio mezcla lógica de backend con presentación gráfica dentro de la Sesión 0. La solución definitiva pasa por una arquitectura desacoplada: servicio sin UI + cliente interactivo. Adoptar esta estructura elimina deadlocks, respeta políticas de seguridad y simplifica el mantenimiento tanto en hardware físico como en entornos virtualizados XCP‑ng.

Aplica la metodología de diagnóstico descrita, refactoriza tu código, limita privilegios y verás cómo los eventos de error desaparecen y tu DC vuelve a iniciar y detener servicios de forma impecable.

Índice