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;