Подтвердить что ты не робот

Как я могу настроить обработку .NET UnhandledException в службе Windows?

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?

4b9b3361

Ответ 1

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

Причина, по которой обработчик CurrentDomain_UnhandledException не попадает в образец кода OP, заключается в том, что метод OnStart вызывается в ответ на команду "Пуск" из диспетчера управления службами Windows (команда получена и отправлена ​​этому методу в рамках реализации ServiceBase Framework); любое исключение, которое выбрано OnStart, обрабатывается в базовом классе, регистрируется в журнале событий и преобразуется в код состояния ошибки, возвращаемый в SCM. Таким образом, исключение никогда не распространяется на обработчик необработанных исключений AppDomain.

Думаю, вы обнаружите, что обработанное CurrentDomain_UnhandledException обработано необработанным исключением из рабочего потока в вашей службе будет.

Ответ 2

В службе 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();
}

Ответ 3

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

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

НТН.

Ответ 4

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

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

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

Ответ 5

Когда я работал над своей собственной службой 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();
        }
    }