ServiceBase.Run, почему я не могу отловить его исключения или как-то реагировать на них? - PullRequest
3 голосов
/ 07 сентября 2011

Я вызываю следующее из статического основного метода моей точки входа:

    try { ServiceBase.Run(new MonitorSer()); }
    catch (Exception ex) { Console.WriteLine(ex.Message + Process.GetCurrentProcess().MainModule.FileName); }

MonitorSer является экземпляром:

class MonitorSer : ServiceBase {

и метод main входа является членом моего класса:

[RunInstaller(true)]
public class WindowsServiceInstaller : Installer {

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

У меня вспыхивает окно с сообщением, что мне нужно установить с помощью installutil, когда я действительно хочу найти имя этого процесса и вызвать его снова с ключом -i, который я подключил, чтобы он сам установился (благодарность тем, кто внес / переработал этот код).

Что делает это более расстраивающим, так это то, что если я установлю точки останова до (или включу) вызова ServiceBase.Run, он молча завершится неудачей, и я останусь с мигающей консолью.

UPDATE

    static void Install(bool undo, string[] args)
    {
        try
        {
            Console.WriteLine(undo ? "uninstalling" : "installing");
            using (AssemblyInstaller inst = new AssemblyInstaller(typeof(MonitorSer).Assembly, args))
            {
                IDictionary state = new Hashtable();
                inst.UseNewContext = true;
                try
                {
                    if (undo) inst.Uninstall(state);
                    else
                    {
                        inst.Install(state);
                        inst.Commit(state);
                    }
                }
                catch
                {
                    try
                    {
                        inst.Rollback(state);
                    }
                    catch { }
                    throw;
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);
        }
    }

Я выбрал здесь точку входа, чтобы я мог вызвать вышеупомянутую функцию, я попробую переместить ее в другой класс и установить там точку входа, но я знаю, что могу сделать эту точку входа (которую вы, Дмитрий, отрицаете) работать, вызывая себя с соответствующим аргументом для установки - что может сделать только класс BaseService - исправьте меня, если я ошибаюсь.

1 Ответ

4 голосов
/ 07 сентября 2011
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer

Не ваша точка входа.Это будет вызвано один раз, когда вы устанавливаете свой сервис, используя InstallUtil.exe.Точка входа может быть указана в свойствах проекта и обычно по умолчанию Program.Main.Вы не должны запускать свой сервис из класса установщика.

CLR сообщит вам о необработанных исключениях, если вы подпишитесь на это событие:

static void Main() {
    ...
    AppDomain.CurrentDomain.UnhandledException 
                                      += CurrentDomain_UnhandledException;
    ...
}

private static void CurrentDomain_UnhandledException(
                                                 Object sender, 
                                                 UnhandledExceptionEventArgs e) {

    if (e != null && e.ExceptionObject != null) {
        // log exception:
    }
}

Это событие предоставляет уведомление о невыполненииисключения.Это позволяет приложению регистрировать информацию об исключении до того, как системный обработчик по умолчанию сообщит об этом исключении пользователю и завершит работу приложения. Начиная с .NET Framework версии 4, это событие не вызывается для исключений, которые повреждают состояниепроцесс, такой как переполнение стека или нарушения доступа, если обработчик события не критичен к безопасности и не имеет атрибут HandleProcessCorruptedStateExceptionsAttribute.application.

Еще одно место, где вы можете регистрировать исключения в службе Windows (поскольку .NET / SCM будет проглатывать исключения при запуске):

protected override void OnStart(String[] args) {
    try {

    } catch(Exception e) {
        // log exception:
        throw;
    }
}
...