Udostępnij za pośrednictwem


Nieobsługiwane wyjątki powodują asp. Aplikacje oparte na platformie NET nieoczekiwanie zamykają się w programie .NET Framework

Ten artykuł pomaga rozwiązać problem polegający na tym, że nieobsługiwane wyjątki powodują asp. Aplikacje oparte na platformie NET nieoczekiwanie zamykają się w programie .NET Framework.

Oryginalna wersja produktu: .NET Framework 4.5
Oryginalny numer KB: 911816

Uwaga 16.

Ten artykuł dotyczy programu Microsoft .NET Framework 2.0 i wszystkich nowszych wersji.

Symptomy

W przypadku zgłoszenia nieobsługiwanego wyjątku na platformie ASP. Aplikacja oparta na platformie NET, która jest oparta na programie .NET Framework 2.0 i nowszych wersjach, aplikacja nieoczekiwanie kończy działanie. W przypadku wystąpienia tego problemu w dzienniku aplikacji nie trzeba rejestrować żadnych informacji o wyjątku, które należy zrozumieć.

Jednak komunikat o zdarzeniu podobny do poniższego przykładu może zostać zarejestrowany w dzienniku systemu. Ponadto w dzienniku aplikacji może zostać zarejestrowany komunikat o zdarzeniu podobny do poniższego przykładu.

Przyczyna

Ten problem występuje, ponieważ domyślne zasady nieobsługiwane wyjątki uległy zmianie w programie .NET Framework 2.0 i nowszych wersjach. Domyślnie zasady nieobsługiwane wyjątki polegają na zakończeniu procesu roboczego.

W programie .NET Framework 1.1 i w programie .NET Framework 1.0 nieobsługiwane wyjątki w wątkach zarządzanych zostały zignorowane. Jeśli nie dołączono debugera w celu przechwycenia wyjątku, nie zdajesz sobie sprawy, że coś jest złe.

ASP.NET używa zasad domyślnych dla nieobsługiwane wyjątki w programie .NET Framework 2.0 i nowszych wersjach. Gdy zgłaszany jest nieobsługiwany wyjątek, asp. Aplikacja oparta na platformie NET nieoczekiwanie kończy działanie.

To zachowanie nie ma zastosowania do wyjątków występujących w kontekście żądania. Tego rodzaju wyjątki są nadal obsługiwane i opakowane przez HttpException obiekt. Wyjątki występujące w kontekście żądania nie powodują zakończenia procesu roboczego. Jednak nieobsługiwane wyjątki poza kontekstem żądania, takie jak wyjątki w wątku czasomierza lub w funkcji wywołania zwrotnego, powodują zakończenie procesu roboczego.

Rozwiązanie 1

Zmodyfikuj kod IHttpModule źródłowy obiektu, aby rejestrował informacje o wyjątkach w dzienniku aplikacji. Zarejestrowane informacje będą zawierać następujące informacje:

  • Ścieżka katalogu wirtualnego, w której wystąpił wyjątek
  • Nazwa wyjątku
  • Komunikat
  • Ślad stosu

Aby zmodyfikować IHttpModule obiekt, wykonaj następujące kroki.

Uwaga 16.

Ten kod rejestruje komunikat o typie zdarzenia błędu i źródle zdarzeń ASP.NET 2.0.50727.0 w dzienniku aplikacji. Aby przetestować moduł, zażądaj strony ASP.NET korzystającej z ThreadPool.QueueUserWorkItem metody w celu wywołania metody, która zgłasza nieobsługiwany wyjątek.

  1. Umieść następujący kod w pliku o nazwie 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. Zapisz plik UnhandledExceptionModule.cs w folderzeC:\Program Files\Microsoft Visual Studio 8\VC.

  3. Otwórz wiersz polecenia programu Visual Studio.

  4. Wpisz sn.exe -k key.snk, a następnie naciśnij ENTER.

  5. Wpisz csc /t:library /r:system.web.dll,system.dll /keyfile:key.snk UnhandledExceptionModule.cs, a następnie naciśnij ENTER.

  6. Wpisz gacutil.exe /if UnhandledExceptionModule.dll, a następnie naciśnij ENTER.

  7. Wpisz ngen install UnhandledExceptionModule.dll, a następnie naciśnij ENTER.

  8. Wpisz gacutil /l UnhandledExceptionModule, a następnie naciśnij ENTER , aby wyświetlić silną nazwę pliku UnhandledExceptionModule .

  9. Dodaj następujący kod do pliku Web.config platformy ASP. Aplikacja oparta na platformie NET.

    <add name="UnhandledExceptionModule"
    type="WebMonitor.UnhandledExceptionModule, <strong name>" />
    

Rozwiązanie 2

Zmień nieobsługiwane zasady wyjątków z powrotem na domyślne zachowanie, które występuje w programie .NET Framework 1.1 i w programie .NET Framework 1.0.

Uwaga 16.

Nie zalecamy zmiany zachowania domyślnego. Jeśli zignorujesz wyjątki, aplikacja może wyciekać zasoby i porzucić blokady.

Aby włączyć to zachowanie domyślne, dodaj następujący kod do pliku Aspnet.config znajdującego się w następującym folderze:
%WINDIR%\Microsoft.NET\Framework\v2.0.50727

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

Stan

Wynika to z ustawienia fabrycznego.

Więcej informacji

Aby uzyskać więcej informacji na temat zmian w programie .NET Framework 2.0, odwiedź stronę Breaking Changes in .NET Framework 2.0 (Istotne zmiany w programie .NET Framework 2.0).