當利用 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 頁面,以呼叫會擲出未處理之例外狀況的方法。
- 將下列程式碼置於名稱為 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);
}
}
} - 將 UnhandledExceptionModule.cs 檔案儲存至下列資料夾:
C:\Program Files\Microsoft Visual Studio 8\VC
- 開啟 Microsoft Visual Studio 2005 的命令提示字元。
- 輸入 sn.exe -k key.snk,然後按下
ENTER。
- 輸入 csc /t:library /r:system.web.dll,system.dll
/keyfile:key.snk UnhandledExceptionModule.cs,然後按下 ENTER。
- 輸入 gacutil.exe /if
UnhandledExceptionModule.dll,然後按下 ENTER。
- 輸入 ngen install
UnhandledExceptionModule.dll,然後按下 ENTER。
- 輸入 gacutil /l
UnhandledExceptionModule 然後按下 ENTER,以顯示 UnhandledExceptionModule 檔案的強式名稱。
- 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) 網站: