Как настроить обработку исключений .NET UnhandledException в службе Windows? - PullRequest
46 голосов
/ 16 марта 2010
protected override void OnStart(string[] args)
{
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    Thread.Sleep(10000);

    throw new Exception();
}

void CurrentDomain_UnhandledException(object sender,
                                      UnhandledExceptionEventArgs e)
{
}

Я подключил отладчик к вышеуказанному коду в моей службе Windows, установив точку останова в CurrentDomain_UnhandledException, но он никогда не срабатывал. Появляется исключение, сообщающее, что оно не обработано, и затем служба останавливается. Я даже пытался поместить некоторый код в обработчик событий, на случай, если он будет оптимизирован.

Разве это не правильный способ настройки обработки необработанных исключений в службе Windows?

Ответы [ 5 ]

54 голосов
/ 25 февраля 2011

Причина, по которой событие UnhandledException на текущем домене приложений не вызывается, заключается в том, как выполняются службы.

  1. Пользователь отправляет команду запуска из диспетчера управления службами Windows (SCM).
  2. Команда получена реализацией ServiceBase платформы и отправлена ​​методу OnStart.
  3. Вызывается метод OnStart.

Любое исключение, которое выдается OnStart, обрабатывается в базовом классе , регистрируется в журнале событий и преобразуется в код состояния ошибки, возвращаемый в SCM. Таким образом, исключение никогда не распространяется на обработчик необработанных исключений AppDomain.

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

9 голосов
/ 27 марта 2010

В службе Windows вы НЕ хотите выполнять много кода в методе OnStart. Все, что вам нужно, это код для запуска потока службы, а затем возврата.

Если вы сделаете это, вы сможете нормально обрабатывать исключения, возникающие в вашем служебном потоке.

, например

public static void Start()
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);

    running = true;
    ThreadStart ts = new ThreadStart(ServiceThreadBody);
    thread = new Thread(ts);
    thread.Name = "ServiceThread";
    thread.Priority = ThreadPriority.BelowNormal;
    thread.Start();
}
4 голосов
/ 12 августа 2017

Когда я работал над собственной службой Windows, она как-то странно остановилась. Я думал, что это из-за беспричинного исключения. На данный момент я ловлю бесполезные исключения в текстовом файле. Прежде всего, вы должны создать новый файл ServiceLog.txt в местах C из-за регистрации исключений в текстовом файле. С кодировкой ниже я получил все неоправданные исключения с номерами строк.

using System.Security.Permissions;
using System.IO;

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    protected override void OnStart(string[] args)
    {   AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
        ...
        Your codes...
        ....
    }
    void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception e = (Exception)args.ExceptionObject;
        WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
    }
    private void WriteToFile(string text)
    {
        string path = "C:\\ServiceLog.txt";
        using (StreamWriter writer = new StreamWriter(path, true))
        {
            writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
            writer.Close();
        }
    }
4 голосов
/ 26 августа 2010

Знаю, что эта ветка немного устарела, но подумал, что было бы полезно добавить некоторые комментарии, основанные на личном опыте разработки служб Windows в .NET. Лучший подход состоит в том, чтобы избегать разработки под Service Control Manager, насколько это возможно - для этого вам понадобится простая система , которая имитирует способ запуска служб - что-то, что может создать экземпляр вашего класса обслуживания (который вы уже получили из ServiceBase) и вызовите методы OnStart, OnStop и т. д. Этот жгут может быть консольным или Windows-приложением по вашему желанию.

Это практически единственный способ отладки проблем запуска службы в .NET - взаимодействие между вашим кодом, Visual Studio и реальным диспетчером управления службами просто делает процесс невозможным в противном случае.

НТН.

2 голосов
/ 16 марта 2010

Просто любопытно, чего вы пытаетесь достичь: избегая сбоя службы или сообщая об ошибках?

Для составления отчетов, я думаю, вам лучше всего добавить операторы try / catch верхнего уровня. Вы можете попытаться записать их в журнал событий Windows и / или файл журнала.

Также можно установить для свойства ExitCode ненулевое значение, пока вы не остановите службу. Если системный администратор запускает вашу службу с панели управления службами, и ваша служба внезапно останавливается с ненулевым кодом выхода, Windows может показать сообщение об ошибке с описанием ошибки.

...