¿Por qué el Medio ambiente.Exit () ¿ya no termina el programa?


Esto es algo que descubrí hace unos días, recibí la confirmación de que no se limita solo a mi máquina de esta pregunta.

La forma más fácil de reprogramarlo es iniciando una aplicación de Windows Forms, agregar un botón y escribir este código:

    private void button1_Click(object sender, EventArgs e) {
        MessageBox.Show("yada");
        Environment.Exit(1);         // Kaboom!
    }

El programa falla después de que se ejecute la instrucción Exit (). En los formularios de Windows se obtiene "Error al crear el controlador de ventana".

Habilitar la depuración no administrada deja algo claro lo que está pasando. El COM el bucle modal se está ejecutando y permite que se entregue un mensaje WM_PAINT. Eso es fatal en una forma dispuesta.

Los únicos hechos que he reunido hasta ahora son:

  • No se limita a ejecutar con el depurador. Esto también falla sin uno. Bastante mal también, el cuadro de diálogo de bloqueo de WER aparece dos veces.
  • No tiene nada que ver con la bitness del proceso. La capa wow64 es bastante notoria, pero una compilación AnyCPU falla de la misma manera manera.
  • No tiene nada que ver con la versión.NET, 4.5 y 3.5 se bloquean de la misma manera.
  • El código de salida no importa.
  • Llamando al hilo.Sleep () antes de llamar a Exit () no lo arregla.
  • Esto sucede en la versión de 64 bits de Windows 8, y Windows 7 no parece verse afectado de la misma manera.
  • Este debería ser un comportamiento relativamente nuevo, no lo he visto antes. No veo actualizaciones relevantes entregadas a través de Windows Update , aunque que el historial de actualizaciones ya no es exacto en mi máquina.
  • Este es un comportamiento groseramente rompedor. Escribirías código como este en un controlador de eventos para AppDomain.UnhandledException, y se bloquea de la misma manera.

Estoy particularmente interesado en lo que podría hacer para evitar este accidente. Particularmente el AppDomain.El escenario UnhandledException me deja atónito; no hay muchas maneras de terminar un programa.NET. Tenga en cuenta que la aplicación de llamada.Exit() o Forma.Close () no son válidos en un controlador de eventos para UnhandledException, por lo que no son soluciones alternativas.


ACTUALIZACIÓN: Mehrdad señaló que el subproceso finalizer podría ser parte del problema. Creo que estoy viendo esto y también estoy viendo alguna evidencia para el 2 segundo tiempo de espera que el CLR da el hilo finalizador para terminar de ejecutar.

El finalizador está dentro de NativeWindow.ForceExitMessageLoop (). Hay una función IsWindow () Win32 allí que aproximadamente corresponde con la ubicación del código, desplazamiento 0x3c cuando se mira el código de la máquina en modo de 32 bits. Parece que IsWindow () está en punto muerto. No puedo obtener un buen seguimiento de pila para los componentes internos, sin embargo, el depurador piensa que la llamada P/Invoke acaba de regresar. Esto es difícil de explicar. Si puedes conseguir un mejor rastreo de pila entonces me encantaría verlo. Mine:

System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12()  + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes

Nada por encima de la llamada ForceExitMessageLoop, depurador no administrado habilitado.

Author: Community, 2013-08-04

4 answers

Me puse en contacto con Microsoft sobre este problema y que parecía haber dado sus frutos. Al menos me gustaría pensar que lo hizo :). Aunque no obtuve una confirmación de una resolución de ellos, el grupo de Windows es difícil de contactar directamente y tuve que usar un intermediario.

Una actualización entregada a través de Windows Update resolvió el problema. El notable retraso de 2 segundos antes del bloqueo ya no está presente, lo que sugiere fuertemente que el punto muerto de IsWindow() se resolvió. Y el el programa se apaga de forma limpia y fiable. La actualización de parches instalados para Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll y wintrust.dll

Uxtheme.dll es el impar-pato hacia fuera. Implementa la API de tematización de estilos visuales y es utilizada por este programa de prueba. No puedo estar seguro, pero mi dinero está en que uno como la fuente del problema. La copia en C:\WINDOWS\system32 tiene el número de versión 6.2.9200.16660, creado el 14 de agosto de 2013 en mi equipo.

, Caso cerrado.

 79
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-24 09:33:28

No se por qué no funciona "más", pero creo que Environment.Exit ejecuta finalizadores pendientes. Environment.FailFast no lo hace.

Podría ser que (por alguna extraña razón) tenga finalizadores pendientes extraños que deben ejecutarse después, causando que esto suceda.

 51
Author: Mehrdad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-03 20:55:45

Esto no explica por qué está sucediendo, pero no llamaría a Environment.Exit en un controlador de eventos de botón como su muestra, sino que cerraría el formulario principal como se sugiere en la respuesta de rene.

En cuanto a un manejador AppDomain.UnhandledException, tal vez podría simplemente establecer Environment.ExitCode en lugar de llamar Environment.Exit.

No estoy seguro de lo que estás tratando de lograr aquí. ¿Por qué desea devolver un código de salida de una aplicación de Windows Forms? Normalmente los códigos de salida son utilizados por las aplicaciones de consola.

Estoy particularmente interesado en lo que podría hacer para evitar este accidente Llamando al Entorno.Exit() es necesario para evitar que se muestre el cuadro de diálogo WER.

¿Tienes un try / catch en el método Principal? Para las aplicaciones de Windows Forms siempre tengo un try / catch alrededor del bucle de mensajes, así como los controladores de excepciones no manejados.

 6
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:00

He encontrado el mismo problema en nuestra aplicación, lo hemos resuelto con la siguiente construcción:

Environment.ExitCode=1;
Application.Exit();
 0
Author: Jesse de Bruijne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-11 08:08:12