Las excepciones no controladas provocan que las aplicaciones basadas en ASP.NET se cierren de forma inesperada en .NET Framework

Este artículo le ayuda a resolver el problema en el que las excepciones no controladas provocan que las aplicaciones basadas en ASP.NET se cierren inesperadamente en .NET Framework.

Versión del producto original:   .NET Framework 4,5
Número de KB original:   911816

Nota

Este artículo se aplica a Microsoft .NET Framework 2,0 y a todas las versiones posteriores.

Síntomas

Cuando se produce una excepción no controlada en una aplicación basada en ASP.NET que se genera en .NET Framework 2,0 y versiones posteriores, la aplicación se cierra inesperadamente. Cuando se produce este problema, no se registra la información de excepción que debe tener para comprender el problema en el registro de la aplicación.

Sin embargo, puede que se registre un mensaje de evento similar al ejemplo siguiente en el registro del sistema. Además, se puede registrar un mensaje de evento similar al ejemplo siguiente en el registro de la aplicación.

Causa

Este problema se produce porque la directiva predeterminada para las excepciones no controladas ha cambiado en .NET Framework 2,0 y versiones posteriores. De forma predeterminada, la Directiva de las excepciones no controladas es finalizar el proceso de trabajo.

En .NET Framework 1,1 y en .NET Framework 1,0, se ignoran las excepciones no controladas en subprocesos administrados. A menos que haya adjuntado un depurador para detectar la excepción, no se dará cuenta de que algo ha fallado.

ASP.NET usa la directiva predeterminada para las excepciones no controladas en .NET Framework 2,0 y versiones posteriores. Cuando se produce una excepción no controlada, la aplicación basada en el ASP.NET se cierra inesperadamente.

Este comportamiento no se aplica a las excepciones que se producen en el contexto de una solicitud. Estos tipos de excepciones todavía se controlan y engloban en un HttpException objeto. Las excepciones que se producen en el contexto de una solicitud no hacen que el proceso de trabajo finalice. Sin embargo, las excepciones no controladas fuera del contexto de una solicitud, como las excepciones en un subproceso de temporizador o en una función de devolución de llamada, provocan que el proceso de trabajo finalice.

Solución 1

Modifique el código fuente del IHttpModule objeto para que registre la información de excepción en el registro de la aplicación. La información que se registra incluirá lo siguiente:

  • La ruta de acceso del directorio virtual en el que se produjo la excepción
  • El nombre de excepción
  • El mensaje
  • El seguimiento de la pila

Para modificar el IHttpModule objeto, siga estos pasos.

Nota

Este código registrará un mensaje que tiene el tipo de evento de error y el origen del evento de ASP.net 2.0.50727.0 en el registro de la aplicación. Para probar el módulo, solicite una página ASP.NET que use el ThreadPool.QueueUserWorkItem método para llamar a un método que inicie una excepción no controlada.

  1. Coloque el siguiente código en un archivo que se denomine UnhandledExceptionModule.CS.

    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using System.Web;
    
    namespace WebMonitor
    {
        public class UnhandledExceptionModule: IHttpModule
        {
    
            static int _unhandledExceptionCount = 0;
            static string _sourceName = null;
            static object _initLock = new object();
            static bool _initialized = false;
    
            public void Init(HttpApplication app)
            {
    
                // Do this one time for each AppDomain.
                if (!_initialized)
                {
                    lock (_initLock)
                    {
                        if (!_initialized)
                        {
                            string webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(),
                            "webengine.dll");
    
                            if (!File.Exists(webenginePath))
                            {
                                throw new Exception(String.Format(CultureInfo.InvariantCulture,
                                                            "Failed to locate webengine.dll at '{0}'.
                                                            This module requires .NET Framework 2.0.",
                                                                  webenginePath));
                            }
    
                            FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
                            _sourceName = string.Format(CultureInfo.InvariantCulture,
                             "ASP.NET {0}.{1}.{2}.0",
                                                        ver.FileMajorPart, ver.FileMinorPart,
                                                         ver.FileBuildPart);
    
                            if (!EventLog.SourceExists(_sourceName))
                            {
                                throw new Exception(String.Format(CultureInfo.InvariantCulture,
                                                            "There is no EventLog source named '{0}'.
                                                            This module requires .NET Framework 2.0.",
                                                                  _sourceName));
                            }
    
                            AppDomain.CurrentDomain.UnhandledException +=
                            new UnhandledExceptionEventHandler(OnUnhandledException);
    
                            _initialized = true;
                        }
                    }
                }
            }
    
            public void Dispose()
            {
            }
    
            void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
            {
                // Let this occur one time for each AppDomain.
                if (Interlocked.Exchange(ref _unhandledExceptionCount, 1) != 0)
                    return;
    
                StringBuilder message = new StringBuilder("\r\n\r\nUnhandledException logged by
                UnhandledExceptionModule.dll:\r\n\r\nappId=");
    
                string appId = (string) AppDomain.CurrentDomain.GetData(".appId");
                if (appId != null)
                {
                    message.Append(appId);
                }
    
                Exception currentException = null;
                for (currentException = (Exception)e.ExceptionObject; currentException != null;
                currentException = currentException.InnerException)
                {
                    message.AppendFormat("\r\n\r\ntype={0}\r\n\r\nmessage={1}
                    \r\n\r\nstack=\r\n{2}\r\n\r\n",
                                         currentException.GetType().FullName,
                                         currentException.Message,
                                         currentException.StackTrace);
                }
    
                EventLog Log = new EventLog();
                Log.Source = _sourceName;
                Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
            }
        }
    }
    
  2. Guarde el archivo UnhandledExceptionModule.CS en la C:\Program Files\Microsoft Visual Studio 8\VC carpeta.

  3. Abra el símbolo del sistema de Visual Studio.

  4. Escriba sn.exe -k key.snk y, a continuación, presione entrar.

  5. Escriba csc /t:library /r:system.web.dll,system.dll /keyfile:key.snk UnhandledExceptionModule.cs y, a continuación, presione entrar.

  6. Escriba gacutil.exe /if UnhandledExceptionModule.dll y, a continuación, presione entrar.

  7. Escriba ngen install UnhandledExceptionModule.dll y, a continuación, presione entrar.

  8. Escriba gacutil /l UnhandledExceptionModule y, a continuación, presione entrar para mostrar el nombre seguro del archivo UnhandledExceptionModule .

  9. Agregue el siguiente código al archivo de Web.config de la aplicación basada en ASP.net.

    <add name="UnhandledExceptionModule"
    type="WebMonitor.UnhandledExceptionModule, <strong name>" />
    

Resolución 2

Cambie la Directiva de excepción no controlada de vuelta al comportamiento predeterminado que se produce en .NET Framework 1,1 y en .NET Framework 1,0.

Nota

No se recomienda cambiar el comportamiento predeterminado. Si omite las excepciones, la aplicación puede perder los recursos y abandonar los bloqueos.

Para habilitar este comportamiento predeterminado, agregue el siguiente código al archivo de Aspnet.config que se encuentra en la siguiente carpeta:
%WINDIR%\Microsoft.NET\Framework\v2.0.50727

<configuration>
     <runtime>
         <legacyUnhandledExceptionPolicy enabled="true" />
     </runtime>
</configuration>

Estado

Este comportamiento es una característica del diseño de la aplicación.

Más información

Para obtener más información acerca de los cambios en .NET Framework 2,0, visite cambios importantes en .NET framework 2,0.