Более простой способ отладки службы Windows

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

Я создал этот билет User Voice. Считайте голосование за это: visualstudio.uservoice.com/forums/121579-visual-studio-ide/…

David 10.09.2018 21:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
335
1
242 352
28
Перейти к ответу Данный вопрос помечен как решенный

Ответы 28

Вы также можете запустить службу из командной строки (sc.exe).

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

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

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

На каком языке ты говоришь?

Что я обычно делаю, так это инкапсулирую логику службы в отдельный класс и запускаю его из класса «бегун». Этот класс бегуна может быть фактической службой или просто консольным приложением. Итак, ваше решение имеет (как минимум) 3 проекта:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....

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

RobS 24.02.2009 07:55

Я думаю, это зависит от того, какую ОС вы используете, Vista гораздо сложнее подключить к службам из-за разделения между сеансами.

Раньше я использовал два варианта:

  • Используйте GFlags (в инструментах отладки для Windows), чтобы настроить постоянный отладчик для процесса. Он существует в разделе реестра «Параметры выполнения файла образа» и очень полезен. Я думаю, вам нужно настроить параметры службы, чтобы включить «Взаимодействие с рабочим столом». Я использую это для всех типов отладки, а не только для сервисов.
  • Другой вариант - немного разделить код, чтобы служебная часть могла быть заменена при обычном запуске приложения. Таким образом, вы можете использовать простой флаг командной строки и запускать как процесс (а не как службу), что значительно упрощает отладку.

Надеюсь это поможет.

+1 для GFlags. Это особенно полезно, если вы не можете изменить исходный код (или если у вас его нет).

Chris Gillum 29.12.2009 06:09

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

При запуске службы я проверяю параметр командной строки «/ debug». Если служба вызывается с этим параметром, я не выполняю обычный запуск службы, а вместо этого запускаю все прослушиватели и просто показываю окно сообщения «Выполняется отладка, для завершения нажмите ОК».

Поэтому, если моя служба запускается обычным способом, она запускается как служба, если она запускается с параметром командной строки / debug, она будет действовать как обычная программа.

В VS я просто добавляю / отлаживаю как параметр отладки и напрямую запускаю служебную программу.

Таким образом, я могу легко отлаживать самые мелкие проблемы. Конечно, кое-что еще нужно будет отладить как сервис, но для 99% этого достаточно.

Когда я пишу службу, я помещаю всю логику службы в проект dll и создаю два «хоста», которые обращаются к этой DLL, один из которых является службой Windows, а другой - приложением командной строки.

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

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

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

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}

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

leppie 24.09.2008 12:19

Правда, тогда вам придется присоединить отладчик к собственно сервисному процессу. Но в большинстве случаев ошибки появляются в любом случае, и разработка становится намного проще.

Maurice 24.09.2008 12:24

Как насчет Debugger.Break () в первой строке?

Ответ принят как подходящий

Если я хочу быстро отладить службу, я просто добавляю туда Debugger.Break(). Когда эта линия будет достигнута, он вернет меня обратно в VS. Не забудьте удалить эту строку, когда закончите.

Обновлено: В качестве альтернативы директивам #if DEBUG вы также можете использовать атрибут Conditional("DEBUG_SERVICE").

[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
    Debugger.Break();
}

На вашем OnStart просто вызовите этот метод:

public override void OnStart()
{
     DebugMode();
     /* ... do the rest */
}

Там код будет включен только во время сборки отладки. Пока вы занимаетесь этим, может быть полезно создать отдельную конфигурацию сборки для отладки службы.

Или вы можете использовать Debugger.Launch (), вам нужно будет включить оператор using для пространства имен Systems.Diagnostics.

Omar Kooheji 24.09.2008 12:39

Ваше сообщение в блоге сработало отлично и спасло мне день :), однако Debugger.Break () у меня не сработал. похоже, что .Net пропускает функцию DebugMode по некоторым причинам, связанным с оптимизацией.

Bizhan 20.12.2011 05:09

Debugger.Launch () у меня работает, а Debugger.Break () - нет. (Процесс завершается с кодом 255.)

Oliver Bock 18.12.2014 05:50

Как вы, ребята, заставляете это работать? Ничего не произошло. Я пробовал Break () и Launch ().

4thSpace 22.03.2016 20:05

@ 4thSpace: 1. Создайте установщик для своей службы, чтобы вы могли установить свою службу. 2. Добавьте строку Debugger.Launch (); в начале вашего Main (). 3. Создайте свой код в режиме отладки. 4. Замените установленные библиотеки DLL отладочными. 5. Запустите службу из панели «Службы Windows». Теперь появляется всплывающее окно с просьбой подключиться к отладчику. Этот способ сработал для меня. Надеюсь и на вас.

ffonz 13.04.2016 11:41

ОБНОВИТЬ

Это самый простой подход:

http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx

Я оставляю свой первоначальный ответ для потомков.


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

Мы обновляем класс и вызываем StartEventLoop () во время запуска службы. (Этот класс также можно легко использовать из консольного приложения.)

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

p.s. How to attach the debugger manually to a running process...?

using System;
using System.Threading;
using System.Configuration;    

public class ServiceEventHandler
{
    Timer _timer;
    public ServiceEventHandler()
    {
        // get configuration etc.
        _timer = new Timer(
            new TimerCallback(EventTimerCallback)
            , null
            , Timeout.Infinite
            , Timeout.Infinite);
    }

    private void EventTimerCallback(object state)
    {
        // do something
    }

    public void StartEventLoop()
    {
        // wait a minute, then run every 30 minutes
        _timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
    }
}

Также я делал следующее (уже упоминалось в предыдущих ответах, но с флагами условного компилятора [#if], чтобы избежать его срабатывания в сборке Release).

Я перестал делать это таким образом, потому что иногда мы забывали собрать Release и имели перерыв отладчика в приложении, работающем на клиентской демонстрации (смущает!).

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif

Что произойдет, если на выполнение // do something потребуется более 30 минут?

Vinod Srivastav 22.10.2018 15:55

Я также думаю, что иметь отдельную «версию» для нормального выполнения и в качестве службы - это выход, но действительно ли для этой цели требуется выделение отдельного переключателя командной строки?

Не могли бы вы просто сделать:

public static int Main(string[] args)
{
  if (!Environment.UserInteractive)
  {
    // Startup as service.
  }
  else
  {
    // Startup as application
  }
}

Это будет иметь «преимущество» в том, что вы можете просто запустить приложение с помощью двойного щелчка (хорошо, если вам это действительно нужно) и что вы можете просто нажать F5 в Visual Studio (без необходимости изменять настройки проекта, чтобы включить этот параметр /console. ).

Технически Environment.UserInteractive проверяет, установлен ли флаг WSF_VISIBLE для текущей оконной станции, но есть ли какая-либо другая причина, по которой он мог бы вернуть false, кроме того, что он был запущен как (неинтерактивная) служба?

Большой! Раньше я использовал метод «if #debug» для запуска как приложение при отладке, иначе как сервис. Это приводит к тому, что приложение не может быть запущено как служба, если вы хотите отладить его, но ваше решение решает эту проблему и позволяет ему запускаться во всех четырех комбинациях службы / приложения и выпуска / отладки.

Jonas 05.03.2010 16:39

Если вы не хотите, чтобы программа запускалась при двойном щелчке (пользователи могут запутаться и запустить несколько экземпляров и т. д.), Вы можете использовать System.Diagnostics.Debugger.IsAttached вместо Environment.UserInteractive.

Blorgbeard 17.05.2010 19:22
но есть ли какая-либо другая причина, по которой он вернет false, кроме того, что он запущен как (неинтерактивная) служба? I can think of one: A scheduled task which does not attach to a console.
Hogan 27.09.2011 00:13

В этом случае я использую параметры командной строки. --install, чтобы установить службу, --uninstall, чтобы удалить службу, и --interactive, чтобы запустить службу как приложение. Я добавляю --interactive в параметры проекта (Отладка> Аргументы команд). Так что я могу легко отлаживать VS. двойной щелчок не приведет к созданию нежелательного запущенного экземпляра, поскольку требуется --interactive. только мои 2 цента.

Emir Akaydın 14.02.2012 20:42

@ EmirAkaydın Да, на самом деле у меня есть параметры командной строки в качестве "резервной копии". Однако я на самом деле разыскивается, чтобы иметь "интерактивный" экземпляр при двойном щелчке, а не сообщение об ошибке о том, что служба не может быть запущена таким образом. Думаю, разные цели ;-)

Christian.K 16.02.2012 13:36

+1 от меня, но для удобства чтения инвертируйте логику, т.е. если Interactive, то RunInteractively иначе RunService :-)

David Keaveny 04.04.2013 03:14

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

Michael Silver 25.06.2017 03:08

Для отладки служб Windows я комбинирую GFlags и файл .reg, созданный с помощью regedit.

  1. Запустите GFlags, указав exe-имя и vsjitdebugger
  2. Запустите regedit и перейдите в то место, где GFlags устанавливает свои параметры.
  3. Выберите «Экспорт ключа» из меню файла.
  4. Сохраните этот файл где-нибудь с расширением .reg.
  5. В любое время, когда вы хотите отладить службу: дважды щелкните файл .reg.
  6. Если вы хотите остановить отладку, дважды щелкните второй файл .reg.

Или сохраните следующие фрагменты и замените servicename.exe на желаемое имя исполняемого файла.


debugon.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag" = "0x00000000"
"Debugger" = "vsjitdebugger.exe"

debugoff.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag" = "0x00000000"

Это все еще работает на Win 7 / Win 2008? Это подход от support.microsoft.com/kb/824344, но он полагается на интерактивные сервисы, и я думал, что их убили? Раньше он всегда был моим предпочтительным вариантом (поскольку при запуске могут возникать проблемы с запуском, когда вставка Debugger.Break () в код может быть неприемлемой).

piers7 09.04.2010 17:20


static void Main()
{
#if DEBUG
                // Run as interactive exe in debug mode to allow easy
                // debugging.

                var service = new MyService();
                service.OnStart(null);

                // Sleep the main thread indefinitely while the service code
                // runs in .OnStart

                Thread.Sleep(Timeout.Infinite);
#else
                // Run normally as service in release mode.

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]{ new MyService() };
                ServiceBase.Run(ServicesToRun);
#endif
}

[Извините за отсутствие объяснения кода - проблемы с уценкой] Должен нормально работать из MS Visual Studio (F5) в отладочных сборках. По-прежнему работает как обычная служба в сборках релизов.

Thomas Bratt 30.09.2008 01:48

Объедините это с решением Кристиана К., приведенным выше, чтобы использовать свойство Environment.UserInteractive, и решение будет действительно чистым и простым.

Ben Robbins 25.03.2010 13:03

OnStart - это protected, и вы не можете изменить уровень доступа :(

Eduard Luca 25.08.2013 00:20

#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif

Я использую вариант ответа JOP. Используя параметры командной строки, вы можете установить режим отладки в IDE со свойствами проекта или через диспетчер служб Windows.

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}

Мне нравится иметь возможность отлаживать каждый аспект моей службы, включая любую инициализацию в OnStart (), при этом выполняя ее с полным поведением службы в рамках SCM ... без режима «консоли» или «приложения».

Я делаю это, создавая вторую службу в том же проекте, чтобы использовать ее для отладки. Служба отладки, когда запускается как обычно (то есть в подключаемом модуле MMC служб), создает процесс узла службы. Это дает вам процесс, к которому можно подключить отладчик, даже если вы еще не запустили свою настоящую службу. После присоединения отладчика к процессу запустите свою настоящую службу, и вы сможете взломать ее в любом месте жизненного цикла службы, включая OnStart ().

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

Подробности:

1) Предполагая, что вы внедряете MyService, также создайте MyServiceDebug. Добавьте оба в массив ServiceBase в Program.cs следующим образом:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService(),
            new MyServiceDebug()
        };
        ServiceBase.Run(ServicesToRun);
    }

2) Добавьте реальную службу И службу отладки в установщик проекта для проекта службы:

Обе службы (настоящая и отладка) включаются, когда вы добавляете выходные данные проекта службы в проект установки для службы. После установки обе службы появятся в плагине MMC service.msc.

3) Запустите службу отладки в MMC.

4) В Visual Studio подключите отладчик к процессу, запущенному службой отладки.

5) Запускаем реальный сервис и наслаждаемся отладкой.

Когда я несколько недель назад создавал новый сервисный проект, я нашел этот пост. Хотя есть много замечательных предложений, я все еще не нашел решения, которое хотел: возможность вызывать методы OnStart и OnStop классов обслуживания без каких-либо изменений в классах обслуживания.

Решение, которое я придумал, использует Environment.Interactive в качестве выбранного режима работы, как это было предложено другими ответами на этот пост.

static void Main()
{
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] 
    {
        new MyService()
    };
    if (Environment.UserInteractive)
    {
        RunInteractive(servicesToRun);
    }
    else
    {
        ServiceBase.Run(servicesToRun);
    }
}

Помощник RunInteractive использует отражение для вызова защищенных методов OnStart и OnStop:

static void RunInteractive(ServiceBase[] servicesToRun)
{
    Console.WriteLine("Services running in interactive mode.");
    Console.WriteLine();

    MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Starting {0}...", service.ServiceName);
        onStartMethod.Invoke(service, new object[] { new string[] { } });
        Console.Write("Started");
    }

    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine(
        "Press any key to stop the services and end the process...");
    Console.ReadKey();
    Console.WriteLine();

    MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Stopping {0}...", service.ServiceName);
        onStopMethod.Invoke(service, null);
        Console.WriteLine("Stopped");
    }

    Console.WriteLine("All services stopped.");
    // Keep the console alive for a second to allow the user to see the message.
    Thread.Sleep(1000);
}

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

Это хороший метод расширения для ServiceBase []. В моем решении несколько служб, поэтому вместо общего базового класса для Program.cs я просто вызываю servicesToRun.RunInteractive (args). Хорошее решение @Anders!

David Keaveny 04.04.2013 03:13

Действительно отличное решение. Я создал простое расширение для ServiceBase [], как предложил Дэвид, которое позволяет запускать службы всего одной строкой кода: pastebin.com/F0fhhG2R

Funbit 26.04.2013 07:41

@Funbit Это действительно здорово - не могли бы вы, если бы я опубликовал это в своем блоге в качестве обновления к пошаговой инструкции?

Anders Abel 26.04.2013 12:14

У меня возникла проблема, когда работа в интерактивном режиме мешает мне отправлять служебные команды через ServiceController. Если у меня запущена служба с именем «MyService», а затем я пытаюсь отправить команду службы, например: (new ServiceController («MyService»)). ExecuteCommand (160); Это не удается, потому что ServiceController возвращает нуль в интерактивном режиме и работает только при работе в качестве службы. затрудняет отладку выполняемых служебных команд.

stephenbayer 21.06.2014 01:44

+1 Мой бывший коллега создал базовый класс EasyRunService (наследующий ServiceProcess), который делает почти то же самое, но без необходимости отражения (потому что OnStart теперь находится в базовом классе). Это действительно упрощает отладку службы Windows.

sondergard 29.01.2015 16:40

У меня нет консоли, использующей решение @Funbit.

Chazt3n 04.05.2016 17:57

Изменение вывода на консольное приложение изменяет установку моего приложения или?

Chazt3n 04.05.2016 18:27

@ Chazt3n Убедитесь, что тип вывода вашего проекта установлен на «Консольное приложение». Что касается установки службы, не имеет значения, какой тип вывода выбран, поведение одинаковое.

Funbit 07.05.2016 04:52

Мне не удалось установить в качестве службы Windows с выбранным CApp, вместо этого я изменил код, ждите навсегда

Chazt3n 09.05.2016 22:19

Тем не менее отличное решение! Единственное, что я бы добавил (как показано в walk through), - это убедиться, что вы зашли в свойства проекта и изменили тип вывода на Console Application, прежде чем пытаться скомпилировать и запустить. Найдите его на Project Properties -> Application -> Output type -> Console Application. Кроме того, для правильной работы мне пришлось запускать приложение с помощью команды start. Пример: C:\"my app name.exe" -service не подойдет для меня. Вместо этого я использовал C:\start /wait "" "my app name.exe" -service

Arvo Bowen 11.07.2016 20:43

+1 Отличное решение (Windows Service - .NET 4.0). Благодарю @Funbit за его методы расширения для ServiceBase в соответствии с его комментарием выше!

Connor Goddard 19.12.2016 15:06

человек ... вы - босс ... также полностью согласен с @ArvoBowen, что нам нужно изменить тип вывода на приложение Console, иначе Console.ReadKey () выдаст исключение и обслуживание будет остановлено.

Naveed Khan 03.06.2020 15:33

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

Короткий ответ: для этого я использую следующий 4 строки кода:

#if DEBUG
    base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
    Debugger.Launch(); // launch and attach debugger
#endif

Они вставляются в метод службы OnStart следующим образом:

protected override void OnStart(string[] args)
{
    #if DEBUG
       base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
       Debugger.Launch(); // launch and attach debugger
    #endif
    MyInitOnstart(); // my individual initialization code for the service
    // allow the base class to perform any work it needs to do
    base.OnStart(args);
}

Для тех, кто не делал этого раньше, я включил подробные подсказки ниже, потому что вы можете легко застрять. Следующие подсказки относятся к Windows 7x64 и Visual Studio 2010 Team Edition, но должны быть действительными и для других сред.


Важный: Разверните службу в "ручной режим (используя утилиту InstallUtil из командной строки VS или запустите подготовленный вами проект установщика службы). Откройте Visual Studio до, вы запустите службу и загрузите решение, содержащее исходный код службы - установите дополнительные точки останова по мере необходимости в Visual Studio - затем запустите службу через Панель управления сервисом.

Из-за кода Debugger.Launch это вызовет диалоговое окно «Необработанное исключение Microsoft .NET Framework в Servicename.exe». появиться. Нажмите IG666 Yes, debug Servicename.exe, как показано на скриншоте:
Elevate

Впоследствии, особенно в Windows 7, UAC может предложить вам ввести учетные данные администратора. Введите их и продолжайте с Yes:

FrameworkException

После этого появляется всем известный Окно JIT-отладчика Visual Studio. Он спрашивает вас, хотите ли вы отлаживать с помощью отключенного отладчика. Прежде чем щелкнуть Yes, выберите, что вы не хочу открывать новый экземпляр (2-й вариант) - новый экземпляр здесь не поможет, потому что исходный код не будет отображаться. Поэтому вы выбираете экземпляр Visual Studio, который вы открыли ранее: UACPrompt

После того, как вы нажали Yes, через некоторое время Visual Studio покажет желтую стрелку прямо в строке, где находится оператор Debugger.Launch, и вы сможете отлаживать свой код (метод MyInitOnStart, который содержит вашу инициализацию). VSDebuggerPrompt

Нажатие F5 немедленно продолжает выполнение,, пока не будет достигнута следующая подготовленная вами точка останова.

Намекать: Чтобы служба продолжала работать, выберите Отладка -> Отключить все. Это позволяет запускать клиент, взаимодействующий со службой после того, как она правильно запустилась и вы закончили отладку кода запуска. Если вы нажмете Shift + F5 (остановить отладку), это прекратит работу службы. Вместо этого вы должны использовать Панель управления сервисом, чтобы остановить его.

Примечание, что

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

  • Я использую Debugger.Launch(), а запускает и подключает отладчик. Я также протестировал Debugger.Break(), который не работало, потому что при запуске службы еще не подключен отладчик (вызывающий «Ошибка 1067: процесс неожиданно завершен».).

  • RequestAdditionalTime устанавливает более длинный тайм-аут для запуска службы (это нет задерживает сам код, но немедленно продолжит выполнение инструкции Debugger.Launch). В противном случае тайм-аут по умолчанию для запуска службы будет слишком коротким, и запуск службы завершится неудачно, если вы не вызовете base.Onstart(args) достаточно быстро из отладчика. Практически 10-минутный тайм-аут позволяет избежать появления сообщения «служба не ответила ... "» сразу после запуска отладчика.

  • Когда вы к нему привыкнете, этот метод станет очень простым, потому что он просто требует, чтобы вы добавили добавить 4 строки к существующему сервисному коду, что позволяет быстро получить контроль и отладить.

Из любопытства знаете ли вы, есть ли тайм-аут для взаимодействия пользователя с пользовательской подсказкой Debugger.Launch ()?

Shiv 25.11.2014 07:54

Как описано, base.RequestAdditionalTime(600000) предотвратит завершение службы управления службой в течение 10 минут, если она не вызовет base.OnStart(args) в течение этого промежутка времени). Кроме того, я помню, что UAC также прервется, если вы не введете учетные данные администратора через некоторое время (я не знаю, сколько именно секунд, но я думаю, вам нужно ввести их в течение минуты, иначе UAC прервется) , что завершит сеанс отладки.

Matt 25.11.2014 12:02

Я обнаружил, что это лучший метод отладки сообщений CustomCommand. +1.

Justin 19.07.2016 16:36

Используйте библиотеку Верхняя полка.

Создайте консольное приложение, затем настройте настройку в главном

class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {

                // setup service start and stop.
                x.Service<Controller>(s =>
                {
                    s.ConstructUsing(name => new Controller());
                    s.WhenStarted(controller => controller.Start());
                    s.WhenStopped(controller => controller.Stop());
                });

                // setup recovery here
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(delayInMinutes: 0);
                    rc.SetResetPeriod(days: 0);
                });

                x.RunAsLocalSystem();
            });
        }
}

public class Controller
    {
        public void Start()
        {

        }

        public void Stop()
        {

        }
    }

Чтобы отладить службу, просто нажмите F5 в Visual Studio.

Чтобы установить службу, введите cmd "console.exe install".

Затем вы можете запускать и останавливать службу в диспетчере служб Windows.

Их лицензирование было слишком запутанным, чтобы понять

Alex Gordon 15.05.2016 23:56

Они используют Apache License afaik. Topshelf - это самый простой способ, который я использовал для разработки и отладки служб Windows. Очень проста в использовании. Разрабатывать как консольное приложение. Установить как службу с одним переключателем командной строки. Настоятельно рекомендуется.

robs 23.01.2018 05:46

TopShelf сэкономил мне массу времени. Спасибо

L_7337 07.05.2019 21:43

Этот Видео на YouTube Фабио Скопеля объясняет, как довольно хорошо отлаживать службу Windows ... Фактический способ выполнения этого начинается в 4:45 на видео ...

Вот код, описанный в видео ... в вашем файле Program.cs добавьте материал для раздела Debug ...

namespace YourNamespace
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
#if DEBUG
            Service1 myService = new Service1();
            myService.OnDebug();
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
#endif

        }
    }
}

В вашем файле Service1.cs добавьте метод OnDebug () ...

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }

    protected override void OnStart(string[] args)
    {
        // your code to do something
    }

    protected override void OnStop()
    {
    }

How it works

По сути, вам нужно создать public void OnDebug(), который вызывает OnStart(string[] args), поскольку он защищен и недоступен снаружи. В программу void Main() добавлен препроцессор #if с #DEBUG.

Visual Studio определяет DEBUG, если проект скомпилирован в режиме отладки. Это позволит выполнить раздел отладки (ниже), когда условие истинно.

Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

И он будет работать так же, как консольное приложение, как только все пойдет хорошо, вы можете изменить режим Release, и обычный раздел else запустит логику

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

Vinod Srivastav 22.10.2018 15:49

Для устранения неполадок в существующей программе службы Windows используйте Debugger.Break (), как предлагали другие ребята.

Для новой программы Windows Service я бы предложил использовать метод Джеймса Майкла Хэра http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template-redux.aspx

У вас есть два варианта отладки.

  1. создать файл журнала: Лично я предпочитаю отдельный файл журнала, такой как текстовый файл, а не с использованием журнала приложения или журнала событий, но это будет стоить вам много времени, потому что все еще трудно определить, где находится точное место ошибки
  2. Преобразуйте приложение в консольное приложение: это позволит вам использовать все инструменты отладки, которые мы можем использовать в VS.

Пожалуйста, обратитесь к сообщению в блоге ЭТО, которое я создал для этой темы.

Просто положите свой обеденный отладчик куда угодно и прикрепите Visualstudio при запуске

#if DEBUG
    Debugger.Launch();
#endif

Также вам нужно запустить VS от имени администратора и разрешить автоматическую отладку процесса другим пользователем (как объяснено здесь):

reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f

Используйте проект C# шаблона службы Windows для создания нового приложения службы https://github.com/HarpyWar/windows-service-template

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

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

[TestMethod]
public void TestMyService()
{
    MyService fs = new MyService();

    var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    OnStart.Invoke(fs, new object[] { null });
}

// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
     string[] par = parameters == null ? null : parameters.ToArray();

     var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

     OnStart.Invoke(service, new object[] { par });
}

Просто вставьте

Debugger.Break();

где угодно в вашем коде.

Например ,

internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main()
        {
            Debugger.Break();
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

Он поразит Debugger.Break();, когда вы запустите свою программу.

static class Program
{
    static void Main()
    {
        #if DEBUG

        // TODO: Add code to start application here

        //    //If the mode is in debugging
        //    //create a new service instance
        Service1 myService = new Service1();

        //    //call the start method - this will start the Timer.
        myService.Start();

        //    //Set the Thread to sleep
        Thread.Sleep(300000);

        //    //Call the Stop method-this will stop the Timer.
        myService.Stop();

         #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };

        ServiceBase.Run(ServicesToRun);
         #endif
    }
}

это проще. просто измените настройку конфигурации решения на отладку, запустите проект / решение, добавьте точки останова по мере продвижения.

Bahamut 30.08.2018 06:59

Лучшим вариантом является использование пространства имен «Система. Диагностика».

Включите свой код в блок if else для режима отладки и режима выпуска, как показано ниже, чтобы переключаться между режимами отладки и выпуска в Visual Studio,

#if DEBUG  // for debug mode
       **Debugger.Launch();**  //debugger will hit here
       foreach (var job in JobFactory.GetJobs())
            {
                //do something 
            }

#else    // for release mode
      **Debugger.Launch();**  //debugger will hit here
     // write code here to do something in Release mode.

#endif

Другие вопросы по теме