未処理の例外によって ASP が発生します。.NET FRAMEWORKで予期せず終了する NET ベースのアプリケーション

この記事は、未処理の例外によって ASP が発生する問題を解決するのに役立ちます。.NET FRAMEWORKで予期せず終了する NET ベースのアプリケーション。

元の製品バージョン: .NET Framework 4.5
元の KB 番号: 911816

注:

この記事は、Microsoft .NET Framework 2.0 以降のすべてのバージョンに適用されます。

現象

ASP で未処理の例外がスローされた場合。.NET Framework 2.0 以降のバージョンに基づいて構築された NET ベースのアプリケーションでは、アプリケーションが予期せず終了します。 この問題が発生した場合、問題を理解するために必要な例外情報はアプリケーション ログに記録されません。

ただし、次の例のようなイベント メッセージがシステム ログに記録される場合があります。 さらに、次の例のようなイベント メッセージがアプリケーション ログに記録される場合があります。

原因

この問題は、.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 のイベント ソース を含むメッセージをアプリケーション ログに記録します。 モジュールをテストするには、 メソッドを使用して未処理の例外をスローするメソッドを 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. 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 の破壊的変更」を参照してください。