未经处理的异常会导致 ASP。基于 NET 的应用程序在.NET Framework中意外退出

本文可帮助你解决未经处理的异常导致 ASP 的问题。基于 NET 的应用程序在.NET Framework意外退出。

原始产品版本:.NET Framework 4.5
原始 KB 编号: 911816

注意

本文适用于 Microsoft .NET Framework 2.0 和所有更高版本。

症状

在 ASP 中引发未经处理的异常时。基于 NET 的应用程序(基于 .NET Framework 2.0 及更高版本)的应用程序意外退出。 出现此问题时,应用程序日志中不会记录必须了解该问题的异常信息。

但是,系统日志中可能会记录类似于以下示例的事件消息。 此外,类似于以下示例的事件消息可能记录在应用程序日志中。

原因

出现此问题的原因是,.NET Framework 2.0 及更高版本中,未经处理的异常的默认策略已更改。 默认情况下,未处理的异常的策略是结束工作进程。

在 .NET Framework 1.1 和 .NET Framework 1.0 中,忽略了托管线程上的未经处理的异常。 除非附加调试器来捕获异常,否则不会发现出现任何错误。

ASP.NET 对 .NET Framework 2.0 及更高版本中的未经处理的异常使用默认策略。 引发未经处理的异常时,ASP 为 。基于 NET 的应用程序意外退出。

此行为不适用于请求上下文中发生的异常。 这些类型的异常仍由 HttpException 对象处理和包装。 请求上下文中发生的异常不会导致工作进程结束。 但是,请求上下文之外的未经处理的异常(例如计时器线程或回调函数中的异常)会导致工作进程结束。

解决方法 1

修改 对象的源代码, IHttpModule 以便它将异常信息记录到应用程序日志中。 记录的信息将包括以下内容:

  • 发生异常的虚拟目录路径
  • 异常名称
  • 消息
  • 堆栈跟踪

若要修改 IHttpModule 对象,请执行以下步骤。

注意

此代码将在应用程序日志中记录一条消息,该消息的事件 类型为“错误 ”, 事件源 ASP.NET 2.0.50727.0 。 若要测试模块,请请求使用 方法调用引发未经处理的异常的方法的 ASP.NET 页 ThreadPool.QueueUserWorkItem

  1. 将以下代码放入名为 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. UnhandledExceptionModule.cs 文件保存到 C:\Program Files\Microsoft Visual Studio 8\VC 文件夹中。

  3. 打开 Visual Studio 命令提示符。

  4. 键入 sn.exe -k key.snk,然后按 Enter

  5. 键入 csc /t:library /r:system.web.dll,system.dll /keyfile:key.snk UnhandledExceptionModule.cs,然后按 Enter

  6. 键入 gacutil.exe /if UnhandledExceptionModule.dll,然后按 Enter

  7. 键入 ngen install UnhandledExceptionModule.dll,然后按 Enter

  8. 键入 gacutil /l UnhandledExceptionModule,然后按 Enter 以显示 UnhandledExceptionModule 文件的强名称。

  9. 将以下代码添加到 ASP 的Web.config 文件中。基于 NET 的应用程序。

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

解决方法 2

将未经处理的异常策略改回 .NET Framework 1.1 和 .NET Framework 1.0 中发生的默认行为。

注意

建议不要更改默认行为。 如果忽略异常,应用程序可能会泄漏资源并放弃锁。

若要启用此默认行为,请将以下代码添加到位于以下文件夹中 的Aspnet.config 文件:
%WINDIR%\Microsoft.NET\Framework\v2.0.50727

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

状态

此行为是设计使然。

更多信息

有关 .NET Framework 2.0 中的更改的详细信息,请访问 .NET Framework 2.0 中的重大更改