Как отлаживать службы Windows в Visual Studio? - PullRequest
75 голосов
/ 13 января 2011

Можно ли отлаживать службы Windows в Visual Studio?

Я использовал код, подобный

System.Diagnostics.Debugger.Break();

, но он выдает некоторую ошибку кода, такую ​​как:

Я получил две ошибки события: eventID 4096 VsJITDebugger и «Служба не ответила своевременно на запрос запуска или управления.»

Ответы [ 16 ]

110 голосов
/ 28 марта 2014

Используйте следующий код в сервисе OnStart метод:

System.Diagnostics.Debugger.Launch();

Выберите параметр Visual Studio во всплывающем сообщении.

Примечание: Чтобы использовать его только в режиме отладки, можно использовать директиву компилятора #if DEBUG следующим образом. Это предотвратит случайную или отладочную работу в режиме выпуска на рабочем сервере.

#if DEBUG
    System.Diagnostics.Debugger.Launch();
#endif
59 голосов
/ 17 января 2011

Вы также можете попробовать это.

  1. Создайте службу Windows, установите и запустите…. То есть службы Windows должны быть запущены в вашей системе.
  2. Во время работы службы перейдите в меню Отладка , нажмите Присоединить процесс (или процесс в старой Visual Studio)
  3. Найдите работающую службу, а затем убедитесь, что Показать процесс от всех пользователей и Показать процессы во всех сеансах выбран, если нет, то выберите его.

enter image description here

  1. Нажмите кнопку Вложить
  2. Нажмите OK
  3. Нажмите Закрыть
  4. Установите точку останова в желаемом месте и дождитесь выполнения. Он будет автоматически отлаживаться всякий раз, когда ваш код достигнет этой точки.
  5. Помните, установите точку останова на достижимом месте , если это onStart (), затем остановите и снова запустите службу

(После долгих поисков я нашел это в разделе «Как отлаживать службы Windows в Visual Studio».)

20 голосов
/ 13 января 2011

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

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

14 голосов
/ 13 января 2011

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

while (!Debugger.IsAttached)
{
    Thread.Sleep(1000);
}

... continue with code

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

6 голосов
/ 16 августа 2013

Учитывая, что ServiceBase.OnStart имеет protected видимость, я пошел по пути отражения, чтобы выполнить отладку.

private static void Main(string[] args)
{
    var serviceBases = new ServiceBase[] {new Service() /* ... */ };

#if DEBUG
    if (Environment.UserInteractive)
    {
        const BindingFlags bindingFlags =
            BindingFlags.Instance | BindingFlags.NonPublic;

        foreach (var serviceBase in serviceBases)
        {
            var serviceType = serviceBase.GetType();
            var methodInfo = serviceType.GetMethod("OnStart", bindingFlags);

            new Thread(service => methodInfo.Invoke(service, new object[] {args})).Start(serviceBase);
        }

        return;
    }
#endif

    ServiceBase.Run(serviceBases);
}

Обратите внимание, что Thread по умолчанию является потоком переднего плана.return извлечение из Main во время работы потоков faux-service не завершит процесс.

4 голосов
/ 13 июля 2017

В статье Microsoft объясняется, как отлаживать службу Windows здесь и какую часть может пропустить любой, если они отладят ее, подключившись к процессу.

Ниже приведен мой рабочий код.Я следовал подходу, предложенному Microsoft.

Добавьте этот код в program.cs:

static void Main(string[] args)
{
    // 'If' block will execute when launched through Visual Studio
    if (Environment.UserInteractive)
    {
        ServiceMonitor serviceRequest = new ServiceMonitor();
        serviceRequest.TestOnStartAndOnStop(args);
    }
    else // This block will execute when code is compiled as a Windows application
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new ServiceMonitor()
        };
        ServiceBase.Run(ServicesToRun);
    }
}

Добавьте этот код в класс ServiceMonitor.

internal void TestOnStartAndOnStop(string[] args)
{
    this.OnStart(args);
    Console.ReadLine();
    this.OnStop();
}

Сейчасперейдите к Свойства проекта , выберите вкладку «Приложение» и выберите Тип вывода как «Консольное приложение» при отладке, или «Приложение Windows», когда завершите отладку, перекомпилируйте и установите службу.

Enter image description here

3 голосов
/ 13 января 2011

Вы можете сделать консольное приложение. Я использую эту main функцию:

    static void Main(string[] args)
    {
        ImportFileService ws = new ImportFileService();
        ws.OnStart(args);
        while (true)
        {
            ConsoleKeyInfo key = System.Console.ReadKey();
            if (key.Key == ConsoleKey.Escape)
                break;
        }
        ws.OnStop();
    }

Мой класс ImportFileService точно такой же, как в приложении моей службы Windows, за исключением наследника (ServiceBase).

2 голосов
/ 19 марта 2015

Я использую параметр /Console в проекте Visual Studio Отладка Параметры запуска Аргументы командной строки :

public static class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
         var runMode = args.Contains(@"/Console")
             ? WindowsService.RunMode.Console
             : WindowsService.RunMode.WindowsService;
         new WinodwsService().Run(runMode);
    }
}


public class WindowsService : ServiceBase
{
    public enum RunMode
    {
        Console,
        WindowsService
    }

    public void Run(RunMode runMode)
    {
        if (runMode.Equals(RunMode.Console))
        {
            this.StartService();
            Console.WriteLine("Press <ENTER> to stop service...");
            Console.ReadLine();

            this.StopService();
            Console.WriteLine("Press <ENTER> to exit.");
            Console.ReadLine();
        }
        else if (runMode.Equals(RunMode.WindowsService))
        {
            ServiceBase.Run(new[] { this });
        }
    }

    protected override void OnStart(string[] args)
    {
        StartService(args);
    }

    protected override void OnStop()
    {
        StopService();
    }

    /// <summary>
    /// Logic to Start Service
    /// Public accessibility for running as a console application in Visual Studio debugging experience
    /// </summary>
    public virtual void StartService(params string[] args){ ... }

    /// <summary>
    /// Logic to Stop Service
    /// Public accessibility for running as a console application in Visual Studio debugging experience
    /// </summary>
    public virtual void StopService() {....}
}
2 голосов
/ 28 сентября 2013

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

    public void MyOnStart(string[] args)
    {
        OnStart(args);
    }
2 голосов
/ 09 августа 2013

Вы также можете попробовать метод System.Diagnostics.Debugger.Launch () .Это помогает перевести указатель отладчика в указанное место, а затем вы можете отладить свой код.

Перед этим шагом , пожалуйста, установите файл service.exe с помощью командной строки командной строки Visual Studio - installutil projectservice.exe

Затем запустите службу из Панель управления -> Администрирование -> Управление компьютером -> Служба и приложение -> Службы -> Имя службы

...