.NET Framework 2.0 で、ハンドルされない例外によって ASP.NET ベースのアプリケーションが突然終了する

文書番号: 911816 - 対象製品
すべて展開する | すべて折りたたむ

目次

現象

Microsoft .NET Framework 2.0 に基づいて構築された Microsoft ASP.NET ベースのアプリケーションで、ハンドルされない例外がスローされると、そのアプリケーションが突然終了します。この問題が発生したとき、問題の理解に必要な例外情報がアプリケーション ログに記録されません。

ただし、次のようなイベント メッセージがシステム ログに記録されることがあります。

種類 : 警告
ソース : W3SVC
分類 : なし
イベント ID : 1009
日付 : 2005/9/28
時刻 : 3:18:11
ユーザー : N/A
コンピュータ : IIS-SERVER
説明 :
アプリケーション プール ‘DefaultAppPool’ を提供しているプロセスが突然終了しました。プロセス id は ‘2548’ でした。プロセス終了コードは ‘0xe0434f4d’ でした。

さらに、次のようなイベント メッセージがアプリケーション ログに記録されることがあります。

種類 : エラー
ソース : .NET Runtime 2.0 Error Reporting
分類 : なし
イベント ID : 5000
日付 : 2005/9/28
時刻 : 3:18:02
ユーザー : N/A
コンピュータ : 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 で変更されたことが原因で発生します。.NET Framework 2.0 のデフォルトのポリシーでは、ハンドルされない例外がスローされた場合、ワーカー プロセスを終了します。

Microsoft .NET Framework 1.1 および Microsoft .NET Framework 1.0 では、マネージ スレッド上のハンドルされない例外は無視されました。このため、デバッガをアタッチして例外をキャッチしない限り、異常は確認できませんでした。

ASP.NET では、ハンドルされない例外に対して .NET Framework 2.0 のデフォルトのポリシーを使用します。ハンドルされない例外がスローされると、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. 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) Web サイトを参照してください。
http://www.microsoft.com/japan/msdn/netframework/programming/breakingchanges/default.aspx

プロパティ

文書番号: 911816 - 最終更新日: 2007年12月3日 - リビジョン: 1.1
この資料は以下の製品について記述したものです。
  • Microsoft .NET Framework 2.0
キーワード:?
kbtshoot kbfix kbprogramming kbprb KB911816
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック