Есть проект. Начальство, спустя более 40к строк кода решило добавить логирование. Обычное, уровня Debug, уже добавил, теперь пришёл черед Exception-ов.
Есть вариант прошить всё try {} catch {log.write(message)}
, но, по-моему, это не самый оптимальный вариант.
Попытался использовать UnhandledExceptionHandler
, однако вне студии (да и банально в запуске без отладки) handler работать не хочет.
Вопрос: не сталкивался ли кто с подобным и что можете посоветовать в таком случае? Т.е. задача: перехватывать все (не только фатальные) исключения в релизе.
Приложение WinForms .NET 2.0 (да, всё настолько плохо:)
Добавлено:
Вешаю Handler
в Main
перед Application.Run(mainForm)
:
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Код обработки
static void UnhandledExceptionHandler(object source, UnhandledExceptionEventArgs e)
{
logger.Error("Message: " + ((Exception)e.ExceptionObject).Message);
var st = new StackTrace(((Exception)e.ExceptionObject), true);
for (int i = 0; i < st.FrameCount; i++)
{
var frame = st.GetFrame(i);
var method = frame.GetMethod();
//if (method.DeclaringType.FullName.Contains("AMT"))
{
logger.Error("Source: " + method.DeclaringType.FullName + "." + method.Name);
logger.Error("Line: " + frame.GetFileLineNumber());
}
}
}
Код просто не отрабатывает, как будто его и нет. В самой студии в режиме отладки всё нормально - и брекпоинт можно поставить, и лог пишется. Как только запускаю .exe напрямую - метода как-будто нет.
Обновление
Решение проблемы:
В Main:
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionHandler);
И три метода, два из которых перехватывают исключения и один вспомогательный для вывода инфы для юзера.
static void UnhandledExceptionHandler(object source, UnhandledExceptionEventArgs e)
{
logger.Error("Message: " + ((Exception)e.ExceptionObject).Message);
var st = new StackTrace(((Exception)e.ExceptionObject), true);
for (int i = 0; i < st.FrameCount; i++)
{
var frame = st.GetFrame(i);
var method = frame.GetMethod();
if (method.DeclaringType.FullName.Contains("AMT"))
{
logger.Error("Source: " + method.DeclaringType.FullName + "." + method.Name);
logger.Error("Line: " + frame.GetFileLineNumber());
}
}
}
private static void ThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
{
logger.Error("Message: " + e.Exception.Message);
var st = new StackTrace(e.Exception, true);
for (int i = 0; i < st.FrameCount; i++)
{
var frame = st.GetFrame(i);
var method = frame.GetMethod();
if (method.DeclaringType.FullName.Contains("AMT"))
{
logger.Error("Source: " + method.DeclaringType.FullName + "." + method.Name);
logger.Error("Line: " + frame.GetFileLineNumber());
}
}
DialogResult result = DialogResult.Cancel;
try
{
result = ShowThreadExceptionDialog("Windows Forms Error", e.Exception);
}
catch
{
try
{
MessageBox.Show("Fatal Windows Forms Error", "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
}
finally
{
Application.Exit();
}
}
if (result == DialogResult.Abort)
Application.Exit();
}
private static DialogResult ShowThreadExceptionDialog(string title, Exception e)
{
string errorMsg = "An application error occurred. Please contact the adminstrator " +
"with the following information:\n\n";
errorMsg = errorMsg + e.Message + "\n\nStack Trace:\n" + e.StackTrace;
return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
}
Подпишитесь на Application.ThreadException
Исключения из ГУИ-потока так ловятся. А вот исключения из прочих потоков, просто крашат приложение, поэтому их пришлось завернуть в try-catch
все.
У меня приведенный код не работает ни под отладчиком, ни без него. Дело в том, что режим UnhandledExceptionMode.CatchException
перенаправляет исключение стандартному обработчику потока (который для основного потока WinForms выводит знаменитое сообщение с красным крестом), и до вашего обработчика ничего не доходит. Замена на UnhandledExceptionMode.ThrowException
решает проблему.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Возникла проблема с WPF: в приложении у меня при нажатии кнопки должен открыться файл с расширениемxlsx и его содержимое перенестись в DataGrid,...
В 2010 студии не работает async | awaitКак показали зарубежные источники, не хватает обновления (т е библиотеки)