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

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

Я использовал код типа

System.Diagnostics.Debugger.Break();

но он дает некоторую ошибку кода, например

Я получил две ошибки: eventID 4096 VsJITDebugger и "Служба не реагировать на запуск или контроль запросить своевременно."

Ответ 1

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

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

enter image description here

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

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

Ответ 2

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

System.Diagnostics.Debugger.Launch();

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

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

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

Ответ 3

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

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

Ответ 4

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

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

... continue with code

Таким образом, вы можете запустить службу, а внутри Visual Studio вы выбираете "Attach to Process..." и присоединяетесь к своей службе, которая затем возобновляет нормальное изъятие.

Ответ 5

Учитывая, что 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 ing из Main, в то время как потоки faux-сервиса работают, это не приведет к завершению процесса.

Ответ 6

Вы можете создать консольное приложение. Я использую эту функцию 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).

Ответ 7

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

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

Затем запустите службу из панели управления → "Администрирование" → "Управление компьютером" → "Сервис и приложение" → "Службы" → "Имя вашей службы"

Ответ 8

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

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

Ответ 9

К сожалению, если вы пытаетесь отладить что-то в самом начале работы службы Windows, "присоединение" к запущенному процессу не будет работать. Я пробовал использовать Debugger.Break() в рамках OnStart procecdure, но с 64-битным компилированным приложением VS 10 команда break просто выдает такую ​​ошибку:

System error 1067 has occurred. 

В этот момент вам нужно будет установить в вашем реестре вариант "Исполнение файла изображения" для вашего исполняемого файла. Для настройки требуется 5 минут, и он работает очень хорошо. Здесь ссылка на MS, где указаны детали:

http://msdn.microsoft.com/en-us/library/a329t4ed(v=vs.100).aspx

Ответ 10

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

    public void MyOnStart(string[] args)
    {
        OnStart(args);
    }

Ответ 11

Кто-нибудь пробовал VS очень собственную командную строку post-build event?

попробуйте добавить это в post-build

@echo off
sc query "ServiceName" > nul
if errorlevel 1060 goto install
goto stop

:delete
echo delete
sc delete "ServiceName" > nul
echo %errorlevel%
goto install

:install
echo install
sc create "ServiceName" displayname= "Service Display Name" binpath= "$(TargetPath)" start= auto > nul
echo %errorlevel%
goto start

:start
echo start
sc start "ServiceName" > nul
echo %errorlevel%
goto end

:stop
echo stop
sc stop "ServiceName" > nul
echo %errorlevel%
goto delete

:end

если ошибка сборки с сообщением типа Error 1 The command "@echo off sc query "ServiceName" > nul и так далее, ctrl-c, то ctrl-v сообщение об ошибке в блокнот и посмотрите последнее предложение сообщения.

можно сказать exited with code x. найдите код в некоторой общей ошибке здесь и посмотрите, как его решить.

1072 -- marked for deletion --> close all apps that maybe using the service including services.msc and windows event log.
1058 -- cant be started because disabled or has no enabled associated devices --> just delete it.
1060 -- doesnt exist --> just delete it.
1062 -- has not been started --> just delete it.
1053 -- didnt response to start or control --> see event log (if logged to event log). it maybe the service itself throw an exception
1056 -- service is already running --> stop the service then delete.

подробнее об ошибке здесь

и если ошибка сборки с сообщением типа

Error   11  Could not copy "obj\x86\Debug\ServiceName.exe" to "bin\Debug\ServiceName.exe". Exceeded retry count of 10. Failed.  ServiceName
Error   12  Unable to copy file "obj\x86\Debug\ServiceName.exe" to "bin\Debug\ServiceName.exe". The process cannot access the file 'bin\Debug\ServiceName.exe' because it is being used by another process. ServiceName

откройте cmd, тогда сначала попробуйте убить его taskkill /fi "services eq ServiceName" /f

если все хорошо, F5 должно быть достаточным для его отладки.

Ответ 12

В статье 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 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", когда это будет сделано при отладке, перекомпиляции и установке вашей службы.  введите описание изображения здесь

Ответ 13

Метод OnStart делает следующее.

protected override void OnStart(string[] args)
        {
            try
            {
                RequestAdditionalTime(600000);
                System.Diagnostics.Debugger.Launch(); // put brake point here.
               ............. your code 
            }
            catch (Exception ex)
            {
                ......... your exception code
            }
        }

затем запустите командную строку как администратор и введите следующие

c:\> sc create test-xyzService binPath= <ProjectPath>\bin\debug\service.exe type= own start= demand

выше строка создаст test-xyzService в списке услуг

Чтобы начать службу, вам будет предложено атташе дебютировать в VS или нет.

c:\> sc start text-xyzService

Чтобы остановить службу

c:\> sc stop test-xyzService 

Чтобы удалить или удалить

c:\> sc delete text-xyzService