Найпростіший спосіб налагодження служби 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 (), вам доведеться включити оператор використання для простору імен The Systems.Diagnostics.
Омар Кухеджі

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

3
Debugger.Launch () працює для мене, коли Debugger.Break () не працює. (Процес виходу з кодом 255.)
Олівер Бок

Як ви, хлопці, змусили це працювати? Нічого не відбувається. Я спробував Break () та Launch ().
простір

13
@ 4thSpace: 1. створіть інсталятор для вашої служби, щоб ви могли встановити службу. 2. Додайте рядок Debugger.Launch (); на початку вашого головного (). 3. Створіть свій код у режимі налагодження. 4. Перезапишіть встановлені DLL-файли за допомогою debug-dll. 5. Запустіть службу на панелі «Служби Windows». Тепер з'являється спливаюче вікно з проханням приєднати до налагоджувача. Цей спосіб спрацював для мене. Сподіваємось і для вас.
ffonz

210

Я також думаю, що окрема "версія" для нормального виконання і як послуга - це шлях, але чи дійсно потрібно для цього виділити окремий комутатор командного рядка?

Чи не могли ви просто зробити:

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

Це матиме "перевагу", що ви можете просто запустити додаток за допомогою подвійного клацання (OK, якщо вам це дійсно потрібно), і ви можете просто натиснути F5в Visual Studio (без необхідності змінювати налаштування проекту, щоб включити цю /consoleопцію).

Технічно Environment.UserInteractiveперевіряється, чи встановлено WSF_VISIBLEпрапор для поточної віконної станції, але чи є якась інша причина, куди він би повертався false, окрім запуску як (неінтерактивної) служби?


Чудово! Раніше я використовував метод "if #debug" для запуску програми як налагодження, інакше послуга. Це призводить до того, що додаток не запускається як послуга, якщо ви хочете налагодити його, але ваше рішення вирішує це, і нехай він може працювати у всіх чотирьох комбінаціях сервісу / програми та випуску / налагодження.
Йонас

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

5
але чи є якась інша причина, коли вона повертає би помилково, окрім того, що вона запускається як (неінтерактивна) послуга? Я можу придумати одне: заплановане завдання, яке не прикріплюється до консолі.
Хоган

7
Я використовую параметри командного рядка для цього випадку. --встановити для встановлення послуги, --встановити для видалення послуги та --інтерактивний запуск служби як програми. я додаю - інтерактив до параметрів проекту (Налагодження> Аргументи команд). Тож я легко можу налагоджувати з VS. подвійне клацання не створить небажаний запущений екземпляр, оскільки - потрібен інтерактив. тільки мої 2 копійки.
Емір Акайдін

@ EmirAkaydın Так, фактично у мене є параметри командного рядка як "резервне копіювання". Однак я насправді хотів мати "інтерактивний" екземпляр, коли двічі клацнув, а не, і повідомлення про помилку про те, що службу неможливо запустити таким чином. Думаю, різні цілі ;-)
Крістіан.К

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!
David Keaveny

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 Debugger . Він запитує, чи хочете ви налагоджувати за допомогою видаленого налагоджувача. Перш ніж натиснути Yes, виберіть, що не хочете відкривати новий екземпляр (2-й варіант) - новий екземпляр тут не буде корисним, оскільки вихідний код не відображатиметься. Таким чином, ви вибираєте екземпляр Visual Studio, який ви відкрили раніше: VSDebuggerPrompt

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

Натискання F5негайно продовжує виконання, поки не буде досягнуто наступного підготовленого пункту розриву.

Підказка: Щоб продовжувати роботу служби, виберіть Налагодження -> Від'єднати всі . Це дозволяє запустити клієнта, який спілкується з сервісом після його правильного запуску, і ви закінчите налагоджувати код запуску. Якщо натиснути Shift+F5 (зупинити налагодження), послуга припинить. Замість цього слід скористатись панеллю управління службою, щоб зупинити її.

Зауважте, що

  • Якщо ви створили Release, тоді код налагодження автоматично видаляється і послуга працює нормально.

  • Я використовую 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

Я залишаю свою оригінальну відповідь нижче для нащадків.


Мої служби, як правило, мають клас, який інкапсулює Таймер, оскільки я хочу, щоб служба регулярно перевіряла, чи є якась робота для цього.

Ми створюємо новий клас та зателефонуємо 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).

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

#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і ви не можете змінити рівень доступу :(
Едуард Лука

10

Ви також можете запустити послугу через командний рядок (sc.exe).

Особисто я би запускав код як окрему програму на етапі налагодження, і коли більшість помилок випрасовується, переходжу до роботи як сервіс.


10

Що раніше я робив, це мати перемикач командного рядка, який запускав би програму або як сервіс, або як звичайний додаток. Потім у своєму IDE я встановив би перемикач, щоб я міг перейти через свій код.

З деякими мовами ви можете фактично визначити, чи працює він в IDE, і виконати цей перемикач автоматично.

Якою мовою ви користуєтесь?


9

Використовуйте TopShelf бібліотеку .

Створіть консольний додаток, а потім налаштуйте налаштування у вашому Main

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 у візуальній студії.

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

Потім ви можете запустити та зупинити службу в менеджері сервісів Windows.


Їх ліцензування було занадто заплутаним, щоб зрозуміти
l --'''''--------- '' '' '' '' '' '15

Вони використовують Afache 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 я поєдную 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"
"Налагоджувач" = "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 () у код може бути не варіантом).
пристани7

1

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

Після запуску послуги я перевіряю параметр командного рядка "/ debug". Якщо служба викликається з цим параметром, я не роблю звичайний запуск сервісу, а замість цього запускаю всіх слухачів і просто показую скриньку повідомлень "Налагодження в процесі роботи, натисніть ОК, щоб закінчити".

Отже, якщо моя служба запускається звичайним способом, вона почне працювати як служба, якщо її запустити з параметру / налагодження командного рядка, вона буде діяти як звичайна програма.

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

Таким чином я можу легко налагоджувати проблеми для більшості дрібних проблем. Звичайно, деякі речі все-таки потрібно буде налагодити як сервіс, але на 99% це досить добре.



1

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

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

1

Для усунення неполадок у існуючій програмі служби Windows використовуйте "Debugger.Break ()", як запропонували інші хлопці.

Для нової програми служби Windows я б запропонував використовувати метод Джеймса Майкла Зайця 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

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

Там консольний / сервісний режим автоматично виявляється, включений автоматичний інсталятор / деінсталятор вашої послуги та кілька найбільш використовуваних функцій.


1

Ось простий метод, який я використовував для тестування служби, без додаткових методів "Налагодження" та з інтегрованими тестами VS Unit.

[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 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.