次の方法で共有


ハンドルされない例外によって ASP が発生します。.NET Framework で予期せず終了する NET ベースのアプリケーション

この記事は、ハンドルされない例外によって ASP が発生する問題を解決するのに役立ちます。.NET Framework で予期せず終了する NET ベースのアプリケーション。

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

Note

この記事は、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 オブジェクトを変更するには、次の手順に従います。

Note

このコードでは、 Event Type of ErrorEvent Source of 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 で発生する既定の動作に戻します。

Note

既定の動作を変更することはお勧めしません。 例外を無視すると、アプリケーションによってリソースがリークされ、ロックが破棄される可能性があります。

この既定の動作を有効にするには、次のフォルダーにある Aspnet.config ファイルに次のコードを追加します。
%WINDIR%\Microsoft.NET\Framework\v2.0.50727

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

状態

この動作は仕様によるものです。

詳細

.NET Framework 2.0 での変更の詳細については、「 .NET Framework 2.0 での変更の更新」を参照してください。