Как вы отлаживаете службу Windows? - PullRequest
46 голосов
/ 01 марта 2011

Я прочитал статью MSDN по этой теме.Цитата:

Поскольку служба должна запускаться из контекста диспетчера служб, а не из Visual Studio, отладка службы не так проста, как отладка других типов приложений Visual Studio.Чтобы отладить сервис, вы должны запустить сервис, а затем подключить отладчик к процессу, в котором он запущен.Затем вы можете отладить ваше приложение, используя все стандартные функции отладки Visual Studio.

Теперь моя проблема заключается в том, что мой сервис не запускается с самого начала.Сначала он вылетает и говорит:

Необработанное исключение (System.Runtime.InteropServices.COMException) произошло в MyServiceName.exe [3596])

и предлагает мнеотладить его (экземпляр отладчика мгновенно падает, когда я выбираю один).Затем он говорит

Не удалось запустить службу MyServiceName на локальном компьютере.Ошибка 1053: Служба не ответила на запрос запуска или управления своевременно

Итак, как я могу выяснить / отладить причину, по которой моя служба не запустилась?Дело в том, что я создал консольное приложение, которое делает ТОЧНО то, что делает служба, и работает нормально.(Я имею в виду, что я просто скопировал метод OnStart () и содержимое основного цикла в main).

Любая помощь приветствуется.

Служба написана на C # с интенсивным использованиемInterop.Я использую VS2008

Ответы [ 15 ]

37 голосов
/ 01 марта 2011

Вы можете использовать параметр, чтобы ваше приложение решало, запускать ли оно как службу или обычное приложение (т.е. в этом случае показывать форму или запускать службу):

static void Main(string[] args)
{
    if ((1 == args.Length) && ("-runAsApp" == args[0]))
    {
        Application.Run(new application_form());
    }
    else
    {
        System.ServiceProcess.ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] { new MyService() };
        System.ServiceProcess.ServiceBase.Run(ServicesToRun);
    }
}

Теперь, если вы передадите параметр "-runAsApp", вы сможете нормально отлаживать приложение - SCM не пропустит этот параметр, поэтому вы также можете использовать его как сервис без каких-либо изменений кода (при условии, что вы наследуете от ServiceBase)

Edit:

Другое отличие от служб Windows - идентификация (это может быть особенно важно для InterOp) - вы хотите убедиться, что вы тестируете под тем же идентификатором в режиме «приложения», а также в режиме службы.

Для этого вы можете использовать олицетворение (я могу опубликовать обертку C #, если это поможет, но это можно легко погуглить) в режиме приложения, чтобы использовать тот же идентификатор, под которым будет работать ваша служба Windows, то есть обычно LocalService или NetworkService.

Если требуется другое удостоверение, вы можете добавить параметры в app.config, которые позволят вам решить, использовать ли учетные данные и, если да, какого пользователя выдавать себя за пользователя - эти параметры будут активны при запуске в качестве приложения, но отключены для служба windows (так как служба уже запущена с нужным именем):

  <appSettings>
    <add key="useCredentials" value="false"/>
    <add key="user" value="Foo"/>
    <add key="password" value="Bar"/>
  </appSettings>
21 голосов
/ 01 марта 2011

Обычно я просто вручную устанавливаю точку останова, а затем указываю на текущий открытый проект в c #. Код для установки точки останова:

System.Diagnostics.Debugger.Break();

Это должно помочь вам начать, тогда вы можете просто просмотреть свой код и посмотреть, что на самом деле происходит.

14 голосов
/ 01 марта 2011

Я украл это у C. Лоуренса Уэнама, поэтому я не могу взять кредит, но вы можете программно подключить отладчик к сервису, БЕЗ прерывания выполнения в этот момент, со следующим кодом:

System.Diagnostics.Debugger.Launch();

Поместите это в метод OnStart () вашего сервиса в качестве первой строки, и он предложит вам выбрать экземпляр VS для присоединения его отладчика.Оттуда система остановится на заданных вами точках останова и на исключениях.Я бы поместил предложение #if DEBUG вокруг кода, чтобы сборка выпуска не включала его;или вы можете просто удалить его после того, как обнаружите проблему.

9 голосов
/ 07 марта 2011

Вы можете использовать WinDbg / NTSD (другой отладчик из пакета «Средства отладки для Windows»), чтобы запустить отладчик вместе с вашим сервисом.

Для этого откройте «gflags» (также доступно в приведенном выше примере).упомянутый пакет) на вкладку «Файл изображения» и укажите путь к исполняемому файлу отладчика для вашего файла образа (службы);

Если ваша служба помечена как интерактивная (возможно, только если она работает под учетной записью SYSTEM), выможет напрямую запустить WinDbg, просто установите для отладчика что-то вроде "PATH_TO_WINDBG \ windbg.exe -g -G" (-g / -G необходимы, чтобы отладчик не прерывал выполнение при запуске приложения)или конец - поведение по умолчанию).Теперь при запуске службы должно появиться окно windbg, которое перехватит любое необработанное исключение.

Если ваша служба не является интерактивной, вы можете запустить отладчик NTSD (отладчик командной строки) в удаленном режиме и подключиться к нему.из WinDbg (который может даже работать на другом ПК).Для этого установите для отладчика в gflags что-то вроде "PATH_TO_NTSD \ ntsd -remote tcp: port = 6666, server = localhost" .Затем подключитесь к удаленному отладчику, запустив windbg что-то вроде "windbg -remote tcp: port = 6666, server = localhost" , и вы должны иметь полный контроль над другим сеансом отладки.

Что касается поиска источника самого исключения, учебник по windbg находится здесь над этой темой, но для начала попробуйте выполнить команду "! Analysis -v" после того, как исключение было обнаружено - с некоторой удачей это всеинформация, которая вам понадобится ..

Примечание: возможно, это излишне для вашего случая, но при таком подходе вы даже можете отлаживать сервисы во время запуска системы (у меня когда-то была проблема с синхронизациейсервис имел проблему только при первом запуске системы)

7 голосов
/ 01 марта 2011

Одна вещь, которую я делаю (которая может быть отчасти хакерской), помещает Thread.Sleep(10000) прямо в начало моего OnStart() метода.Это дает мне 10-секундное окно для присоединения моего отладчика к службе, прежде чем он сделает что-либо еще.

Конечно, я удаляю оператор Thread.Sleep(), когда я закончу отладку.другое, что вы можете сделать, это:

public override void OnStart()
{
    try
    {
        // all your OnStart() logic here
    }
    catch(Exception ex)
    {
        // Log ex.Message
        if (!EventLog.SourceExists("MyApplication"))
            EventLog.CreateEventSource("MyApplication", "Application");

        EventLog.WriteEntry("MyApplication", "Failed to start: " + ex.Message);
        throw;
    }
}

Когда вы регистрируете ex.Message, вы можете получить более подробное сообщение об ошибке.Кроме того, вы можете просто войти ex.ToString(), чтобы получить трассировку всего стека, и если ваши файлы .pdb находятся в том же каталоге, что и ваш исполняемый файл, он даже скажет вам, на какой строке произошло исключение.

6 голосов
/ 01 марта 2011

Добавьте много подробных записей в свой OnStart. Это больно и старая школа, но это работает.

5 голосов
/ 06 марта 2011

Похоже, проблема в пользовательском контексте. Позвольте мне подтвердить, верны ли мои предположения.

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

  2. Когда вы говорите, что при вызове из службы Windows происходит сбой того же кода, я предполагаю, что служба работает под учетной записью «Локальная система» на компьютере разработчика.

Если оба моих предположения верны, попробуйте выполнить следующие действия.

  1. В списке услуг щелкните правой кнопкой мыши свой сервис, выберите свойства и перейдите на вкладку «Вход».

  2. Выберите опцию «Эта учетная запись» и укажите существующее имя пользователя и пароль.

  3. Теперь попробуйте запустить службу. Теперь он должен запуститься без ошибок.

Следующее может быть основной причиной вашей ошибки

  1. Если вы используете SQL Server, убедитесь, что вы не используете аутентификацию SSPI.

  2. Если вы пытаетесь прочитать любую общую папку \ ресурс, на которую у вас нет прав при использовании учетной записи «локальной системы».

  3. Если какая-либо из требуемых зависимостей, требуемых приложением, находится в другой папке, к которой у пользователя «Локальная система» нет прав доступа.

  4. Если вы используете автоматизацию VBA, которая не работает в учетной записи «Local System».

  5. Попробуйте отключить брандмауэр или антивирус.

4 голосов
/ 01 марта 2011

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

Также службы по умолчанию не связаны с рабочим столом;если вы откроете апплет панели управления services.msc, получите свойства своего сервиса, перейдите на вкладку «Вход в систему», вы можете установить флажок «Разрешить сервису взаимодействовать с рабочим столом».Это может решить проблему для вас в некоторых случаях.

3 голосов
/ 01 марта 2011

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

После этого процесс присоединения отладчика довольно прост из Visual Studio Debug-> Attach To Process.

3 голосов
/ 01 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...