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


325

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


Я создал этот билет User Voice. Рассмотрите возможность голосования за это: visualstudio.uservoice.com/forums/121579-visual-studio-ide/…
Дэвид

Ответы:


271

Если я хочу быстро отладить сервис, я просто падаю в 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 */
}

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


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

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

3
Debugger.Launch () работает для меня, когда Debugger.Break () нет. (Процесс завершается с кодом 255.)
Оливер Бок

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

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

210

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

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

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» для запуска в качестве приложения при отладке, в противном случае - в качестве службы. Это приводит к тому, что приложение не может быть запущено как сервис, если вы хотите его отладить, но ваше решение решает эту проблему и позволяет запускать его во всех четырех комбинациях сервис / приложение и выпуск / отладка.
Йонас

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

5
но есть ли какая-либо другая причина, по которой он будет возвращать false, кроме как запуск (неинтерактивный) сервис? Я могу думать об одном: запланированное задание, которое не присоединяется к консоли.
Хоган

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

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

123

Когда я создал новый сервисный проект несколько недель назад, я нашел этот пост. Хотя было много замечательных предложений, я так и не нашел решение, которое хотел: возможность вызывать классы обслуживания 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!
Дэвид Кивини

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

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

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

2
Все еще отличное решение! Единственное, что я хотел бы добавить (как показано на рисунке 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
Арво Боуэн

47

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

Краткий ответ: я использую следующие 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 ». появляться. Нажмите, как показано на скриншоте:Elevate Yes, debug Servicename.exe
FrameworkException

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

UACPrompt

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

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

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

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

Обратите внимание, что

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

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

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

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


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

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

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

40

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

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

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

27

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

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

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()
    {
    }

Как это устроено

По сути, вы должны создать объект, 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раздел вызовет логику


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

14

ОБНОВИТЬ

Этот подход, безусловно, самый простой:

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

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


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

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

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

ps Как вручную прикрепить отладчик к запущенному процессу ...?

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 минут?
Винод Шривастав

13

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) в отладочных сборках. Все еще работает как нормальная служба в сборках релиза.
Томас Братт

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

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

10

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

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


10

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

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

Какой язык вы используете?


9

Используйте библиотеку TopShelf .

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

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.


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

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

TopShelf сэкономил мне кучу времени. Thx
L_7337

8

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

Два варианта, которые я использовал в прошлом:

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

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


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

6

Мне нравится иметь возможность отлаживать каждый аспект моего сервиса, включая любую инициализацию в 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) Запустите реальный сервис и наслаждайтесь отладкой.


5

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

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

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


4

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

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

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

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


2

Для отладки Windows Services я объединяю GFlags и файл .reg, созданный regedit.

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

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


debugon.reg:

Редактор реестра Windows, версия 5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Параметры выполнения файла изображения \ servicename.exe]
"GlobalFlag" = "0x00000000"
"Debugger" = "vsjitdebugger.exe"

debugoff.reg:

Редактор реестра Windows, версия 5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Параметры выполнения файла изображения \ servicename.exe]
"GlobalFlag" = "0x00000000"

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

1

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

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

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

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

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



1

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

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

1

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

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


1

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

#if DEBUG
    Debugger.Launch();
#endif

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

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

1

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

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


1

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

[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 });
}

1
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
    }
}

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

0

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

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

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


0

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

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();когда вы запустите вашу программу.


0

Наилучшим вариантом является использование пространства имен System.Diagnostics .

Включите ваш код в блок 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.