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

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

321
задан 6 revs, 5 users 50% 4 November 2016 в 10:52
поделиться

15 ответов

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

Там, код будет только включен во время сборок Отладки. В то время как Ваш в нем, могло бы быть полезно создать отдельную Конфигурацию сборки для сервисной отладки.

269
ответ дан shA.t 23 November 2019 в 00:56
поделиться
#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif
1
ответ дан Ervin Ter 23 November 2019 в 00:56
поделиться

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

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

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

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

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

1
ответ дан Sam 23 November 2019 в 00:56
поделиться

К Сервисам окон отладки я комбинирую GFlags и .reg файл, созданный regedit.

  1. Выполнение GFlags, определяя exe-имя и Выполнение vsjitdebugger
  2. regedit и переходят к местоположению, где GFlags устанавливает его опции
  3. , Выбирают, "Export Key" из меню файла
  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"
2
ответ дан 23 November 2019 в 00:56
поделиться

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

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}
4
ответ дан Maurice 23 November 2019 в 00:56
поделиться

Как насчет Отладчика. Повреждение () в первой строке?

4
ответ дан leppie 23 November 2019 в 00:56
поделиться

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

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

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

5
ответ дан Nir 23 November 2019 в 00:56
поделиться

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

Эти две опции, которые я использовал в прошлом:

  • Использование GFlags (в Средствах отладки для Windows) для установки постоянного отладчика для процесса. Это существует в "ключе реестра" Опций Выполнения Файла изображения и невероятно полезно. Я думаю, что необходимо будет настроить настройки Service для включения, "Взаимодействуют с Рабочим столом". Я использую это для всех типов отладки, не просто услуг.
  • другая опция, должен разделить код немного, так, чтобы запасная часть была interchangable с нормальным запуском приложения. Тем путем можно использовать простой флаг командной строки и запуститься как процесс (а не Сервис), который делает намного легче отладить.

Hope это помогает.

8
ответ дан RichS 23 November 2019 в 00:56
поделиться

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

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

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

10
ответ дан RB. 23 November 2019 в 00:56
поделиться

Можно также запустить сервис через командную строку (sc.exe).

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

10
ответ дан akauppi 23 November 2019 в 00:56
поделиться
<час>
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
}
13
ответ дан Thomas Bratt 23 November 2019 в 00:56
поделиться

ОБНОВЛЕНИЕ

Этот подход является безусловно самым легким:

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

я оставляю свой исходный ответ ниже для потомства.

<час>

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

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

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

p.s. , Как присоединить отладчик вручную к рабочему процессу...?

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] флаги, чтобы помочь избежать его стреляющий в Сборку конечных версий).

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

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif
14
ответ дан rohancragg 23 November 2019 в 00:56
поделиться

То, что я обычно делаю, инкапсулируют логику сервиса в отдельном классе и запускают это с класса 'бегуна'. Этот класс бегуна может быть практической эксплуатацией или просто консольным приложением. Таким образом, Ваше решение имеет (по крайней мере) 3 проекта:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....
40
ответ дан Paul van Brenk 23 November 2019 в 00:56
поделиться

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

не Мог Вы просто сделать:

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 кроме того, чтобы быть выполненным как (неинтерактивный) сервис?

209
ответ дан Christian.K 23 November 2019 в 00:56
поделиться

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

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}
1
ответ дан 23 November 2019 в 00:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: