IIS Recycle Global.asax

Можно ли перехватить событие recycle в global.asax?

Я знаю, что Application_End будет запущен, но есть ли способ узнать, что он был вызван перезапуском пула приложений?

THX, Ливен Кардоен ака Johlero

4 ответа

Решение

Итак, вот идея, как это могло бы работать.

На основании моего предыдущего ответа (прикрепить к AppDomain.CurrentDomain.ProcessExit) и комментария stephbu:

Это приведет к ловушке большинства структурных разрывов процессов, например - но я не уверен, что это приведет к ловушке всех разрывов. например, http://blogs.msdn.com/jmstall/archive/2006/11/26/process-exit-event.aspx процесса уничтожит процесс, если он кажется зависшим - ваш обработчик не будет вызван.

Я предлагаю следующую стратегию:

В (обычном) обработчике ProcessExit (который, как мы полагаем, не будут вызываться при перезапуске пула приложений), запишите какой-нибудь файл на диск, например "app_domain_end_ok.tmp".

Затем в Application_Start вашего global.asax проверьте этот файл. Если это не существует, это признак того, что приложение не было завершено чистым способом (или это - первый раз, когда это запустилось). Не забудьте удалить этот файл с диска после проверки.

Я сам не пробовал, но стоит попробовать.

Я нашел эту статью в блоге Скотта Гатриса:

Ведение журнала событий закрытия приложений ASP.NET

Кто-то из listserv недавно спросил, есть ли способ выяснить, почему и когда ASP.NET перезапускает домены приложений. В частности, он искал точную причину их запуска в своем приложении в производственной общедоступной среде (было ли это изменение файла web.config, изменение global.asax, изменение каталога app_code, изменение удаления каталога, макс. -num-compilations достигли квоты, \bin, изменение каталога и т. д.).

У Томаса в моей команде есть классный фрагмент кода, который он написал, который использует некоторые хитрые уловки с частным отражением для сбора и записи этой информации. Его довольно легко повторно использовать и добавлять в любое приложение, и его можно использовать для регистрации информации в любом месте (в приведенном ниже коде для сохранения используется журнал событий NT), но вы также можете легко отправить его в базу данных или по электронной почте администратору). Код работает как с ASP.NET V1.1, так и с ASP.NET V2.0.

Просто добавьте пространства имен System.Reflection и System.Diagnostics в свой класс / файл Global.asax, а затем добавьте событие Application_End со следующим кодом:

public void Application_End() {

    HttpRuntime runtime = 
       (HttpRuntime) typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime",
          BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, 
          null, null, null);

    if (runtime == null)
        return;

    string shutDownMessage = 
       (string) runtime.GetType().InvokeMember("_shutDownMessage",
           BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
           null, runtime, null);

    string shutDownStack = 
       (string) runtime.GetType().InvokeMember("_shutDownStack",
           BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
           null, runtime, null);

    if (!EventLog.SourceExists(".NET Runtime")) {
        EventLog.CreateEventSource(".NET Runtime", "Application");
    }

    EventLog log = new EventLog();
    log.Source = ".NET Runtime";

    log.WriteEntry(String.Format(
          "\r\n\r\n_shutDownMessage={0}\r\n\r\n_shutDownStack={1}", 
          shutDownMessage, shutDownStack),
       EventLogEntryType.Error);
}

Я никогда не пробовал это сам, но вы можете попытаться присоединить обработчик событий к событию ProcessExit в AppDomain.

...
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnExit);
...

void OnExit(object sender, EventArgs e) {
    // do something
}

Надеюсь, это поможет!

Я был гораздо более успешным с присоединением к событию DomainUnload, оно запускается при перезапуске AppPool и остановке самого AppPool.

AppDomain.CurrentDomain.DomainUnload += this.CurrentDomainOnProcessExit;

Другие вопросы по тегам