文章編號: 911816 - 上次校閱: 2007年12月3日 - 版次: 1.4

未處理的例外狀況會導致 ASP.NET 應用程式在 .NET Framework 2.0 中意外結束

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

徵狀

當利用 Microsoft .NET Framework 2.0 所建置之 Microsoft ASP.NET 應用程式擲出未處理的例外狀況時,該應用程式會意外結束。發生此問題時,並不會在應用程式記錄檔中記錄任何有助於了解此問題的例外狀況資訊。

但可能會在系統記錄檔中記錄類似下列的事件訊息:

事件類型: 警告
事件來源: W3SVC
事件類別: 無
事件識別碼: 1009
日期: 9/28/2005
時間: 3:18:11
PM 使用者: 不適用
電腦: IIS-SERVER
描述:
服務應用程式集區 'DefaultAppPool' 的處理程序意外終止。處理程序識別碼為 '2548'。處理程序結束碼為 '0xe0434f4d'。

此外也可能在應用程式記錄檔中記錄類似下列的事件訊息:

事件類型: 錯誤
事件來源: .NET Runtime 2.0 錯誤報告
事件類別: 無
事件識別碼: 5000
日期: 9/28/2005
時間: 下午 3:18:02
使用者: 不適用
電腦: IIS-SERVER
描述:
EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 42435be1, P4 app_web_7437ep-9, P5 0.0.0.0, P6 433b1670, P7 9, P8 a, P9 system.exception, P10 NIL。

發生的原因

此問題起因於未處理之例外狀況的預設原則,在 .NET Framework 2.0 中已有所變更。未處理之例外狀況的原則預設會結束工作者處理程序。

在 Microsoft .NET Framework 1.1 與 Microsoft .NET Framework 1.0 中,會忽略受管理執行緒之未處理的例外狀況。除非連接偵錯工具捕捉例外狀況,否則將無法測知任何錯誤。

對於 .NET Framework 2.0 中之未處理的例外狀況,ASP.NET 會使用預設原則。當擲出未處理的例外狀況時,ASP.NET 應用程式即會意外結束。

此行為不適用於要求內容中所發生的例外狀況。這些類型的例外狀況仍會由 HttpException 物件進行處理及包裝。要求內容中所發生的例外狀況不會導致工作者處理程序結束。但要求內容外部所發生之未處理的例外狀況 (如計時器執行緒或回呼函式的例外) 則會導致工作者處理程序結束。

解決方案

如果要解決這個問題,請使用下列其中一種方法。

方法 1

修改 IHttpModule 物件的原始程式碼,使其在應用程式記錄檔中記錄例外狀況的資訊。所記錄的資訊將包括:
  • 發生例外狀況所在的虛擬目錄路徑
  • 例外狀況的名稱
  • 訊息
  • 堆疊追蹤
如果要修改 IHttpModule 物件,請依照下列步驟執行。

注意 此程式碼會將事件類型為錯誤及事件來源為 ASP.NET 2.0.50727.0 的訊息,記錄到應用程式記錄檔中。如果要測試此模組,請要求使用 ThreadPool.QueueUserWorkItem 方法的 ASP.NET 頁面,以呼叫會擲出未處理之例外狀況的方法。
  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. 開啟 Microsoft Visual Studio 2005 的命令提示字元。
  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. 9. 將下列程式碼加入 ASP.NET 應用程式的 Web.config 檔案中。
    <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 之變更內容的詳細資訊,請造訪下列 Microsoft Developer Network (MSDN) 網站:
http://msdn2.microsoft.com/en-us/netframework/aa570326.aspx (http://msdn2.microsoft.com/en-us/netframework/aa570326.aspx)

這篇文章中的資訊適用於:
  • Microsoft .NET Framework 2.0
關鍵字:?
kbtshoot kbfix kbprogramming kbprb KB911816
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。