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





Вы также можете запустить службу из командной строки (sc.exe).
Лично я бы запустил код как отдельную программу на этапе отладки, а когда большинство ошибок будет устранено, перейду на работу как службу.
Раньше я использовал переключатель командной строки, который запускал бы программу либо как службу, либо как обычное приложение. Затем в своей среде IDE я бы установил переключатель, чтобы я мог выполнять свой код.
С некоторыми языками вы действительно можете определить, работает ли он в среде IDE, и выполнить это переключение автоматически.
На каком языке ты говоришь?
Что я обычно делаю, так это инкапсулирую логику службы в отдельный класс и запускаю его из класса «бегун». Этот класс бегуна может быть фактической службой или просто консольным приложением. Итак, ваше решение имеет (как минимум) 3 проекта:
/ConsoleRunner
/....
/ServiceRunner
/....
/ApplicationLogic
/....
Раньше я тоже использовал этот подход, но я думаю, что сочетание этого и вышеприведенного ответа дает удовольствие.
Я думаю, это зависит от того, какую ОС вы используете, Vista гораздо сложнее подключить к службам из-за разделения между сеансами.
Раньше я использовал два варианта:
Надеюсь это поможет.
+1 для GFlags. Это особенно полезно, если вы не можете изменить исходный код (или если у вас его нет).
Для рутинного программирования небольших вещей я сделал очень простой трюк, чтобы легко отлаживать мою службу:
При запуске службы я проверяю параметр командной строки «/ debug». Если служба вызывается с этим параметром, я не выполняю обычный запуск службы, а вместо этого запускаю все прослушиватели и просто показываю окно сообщения «Выполняется отладка, для завершения нажмите ОК».
Поэтому, если моя служба запускается обычным способом, она запускается как служба, если она запускается с параметром командной строки / debug, она будет действовать как обычная программа.
В VS я просто добавляю / отлаживаю как параметр отладки и напрямую запускаю служебную программу.
Таким образом, я могу легко отлаживать самые мелкие проблемы. Конечно, кое-что еще нужно будет отладить как сервис, но для 99% этого достаточно.
Когда я пишу службу, я помещаю всю логику службы в проект dll и создаю два «хоста», которые обращаются к этой DLL, один из которых является службой Windows, а другой - приложением командной строки.
Я использую приложение командной строки для отладки и подключаю отладчик к реальной службе только для ошибок, которые я не могу воспроизвести в приложении командной строки.
Если вы используете этот подход, просто помните, что вам нужно тестировать весь код во время работы в реальном сервисе, а инструмент командной строки - хорошее средство отладки, это другая среда, и он не ведет себя точно так же, как реальный сервис.
При разработке и отладке службы Windows я обычно запускаю ее как консольное приложение, добавляя параметр запуска / console и проверяя его. Делает жизнь намного проще.
static void Main(string[] args) {
if (Console.In != StreamReader.Null) {
if (args.Length > 0 && args[0] == "/console") {
// Start your service work.
}
}
}
До тех пор, пока вам не придется отлаживать проблемы, связанные с сервисом.
Правда, тогда вам придется присоединить отладчик к собственно сервисному процессу. Но в большинстве случаев ошибки появляются в любом случае, и разработка становится намного проще.
Как насчет Debugger.Break () в первой строке?
Если я хочу быстро отладить службу, я просто добавляю туда 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 */
}
Там код будет включен только во время сборки отладки. Пока вы занимаетесь этим, может быть полезно создать отдельную конфигурацию сборки для отладки службы.
Или вы можете использовать Debugger.Launch (), вам нужно будет включить оператор using для пространства имен Systems.Diagnostics.
Ваше сообщение в блоге сработало отлично и спасло мне день :), однако Debugger.Break () у меня не сработал. похоже, что .Net пропускает функцию DebugMode по некоторым причинам, связанным с оптимизацией.
Debugger.Launch () у меня работает, а Debugger.Break () - нет. (Процесс завершается с кодом 255.)
Как вы, ребята, заставляете это работать? Ничего не произошло. Я пробовал Break () и Launch ().
@ 4thSpace: 1. Создайте установщик для своей службы, чтобы вы могли установить свою службу. 2. Добавьте строку Debugger.Launch (); в начале вашего Main (). 3. Создайте свой код в режиме отладки. 4. Замените установленные библиотеки DLL отладочными. 5. Запустите службу из панели «Службы Windows». Теперь появляется всплывающее окно с просьбой подключиться к отладчику. Этот способ сработал для меня. Надеюсь и на вас.
ОБНОВИТЬ
Это самый простой подход:
http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx
Я оставляю свой первоначальный ответ для потомков.
Мои службы, как правило, имеют класс, который инкапсулирует таймер, поскольку я хочу, чтобы служба регулярно проверяла, есть ли для нее какая-либо работа.
Мы обновляем класс и вызываем StartEventLoop () во время запуска службы. (Этот класс также можно легко использовать из консольного приложения.)
Приятным побочным эффектом такой конструкции является то, что аргументы, с помощью которых вы настраиваете таймер, можно использовать для задержки до того, как служба фактически начнет работать, так что у вас будет время подключить отладчик вручную.
p.s. How to attach the debugger manually to a running process...?
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 минут?
Я также думаю, что иметь отдельную «версию» для нормального выполнения и в качестве службы - это выход, но действительно ли для этой цели требуется выделение отдельного переключателя командной строки?
Не могли бы вы просто сделать:
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» для запуска как приложение при отладке, иначе как сервис. Это приводит к тому, что приложение не может быть запущено как служба, если вы хотите отладить его, но ваше решение решает эту проблему и позволяет ему запускаться во всех четырех комбинациях службы / приложения и выпуска / отладки.
Если вы не хотите, чтобы программа запускалась при двойном щелчке (пользователи могут запутаться и запустить несколько экземпляров и т. д.), Вы можете использовать System.Diagnostics.Debugger.IsAttached вместо Environment.UserInteractive.
В этом случае я использую параметры командной строки. --install, чтобы установить службу, --uninstall, чтобы удалить службу, и --interactive, чтобы запустить службу как приложение. Я добавляю --interactive в параметры проекта (Отладка> Аргументы команд). Так что я могу легко отлаживать VS. двойной щелчок не приведет к созданию нежелательного запущенного экземпляра, поскольку требуется --interactive. только мои 2 цента.
@ EmirAkaydın Да, на самом деле у меня есть параметры командной строки в качестве "резервной копии". Однако я на самом деле разыскивается, чтобы иметь "интерактивный" экземпляр при двойном щелчке, а не сообщение об ошибке о том, что служба не может быть запущена таким образом. Думаю, разные цели ;-)
+1 от меня, но для удобства чтения инвертируйте логику, т.е. если Interactive, то RunInteractively иначе RunService :-)
Я также использую этот подход, он действительно великолепен для запуска тестов и т. д., Но могут возникнуть проблемы с запуском приложения в разных контекстах, например, если вы хотите сделать снимок экрана.
Для отладки служб Windows я комбинирую GFlags и файл .reg, созданный с помощью regedit.
Или сохраните следующие фрагменты и замените 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"
Это все еще работает на Win 7 / Win 2008? Это подход от support.microsoft.com/kb/824344, но он полагается на интерактивные сервисы, и я думал, что их убили? Раньше он всегда был моим предпочтительным вариантом (поскольку при запуске могут возникать проблемы с запуском, когда вставка Debugger.Break () в код может быть неприемлемой).
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, и вы не можете изменить уровень доступа :(
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
Я использую вариант ответа JOP. Используя параметры командной строки, вы можете установить режим отладки в IDE со свойствами проекта или через диспетчер служб Windows.
protected override void OnStart(string[] args)
{
if (args.Contains<string>("DEBUG_SERVICE"))
{
Debugger.Break();
}
...
}
Мне нравится иметь возможность отлаживать каждый аспект моей службы, включая любую инициализацию в 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) Запускаем реальный сервис и наслаждаемся отладкой.
Когда я несколько недель назад создавал новый сервисный проект, я нашел этот пост. Хотя есть много замечательных предложений, я все еще не нашел решения, которое хотел: возможность вызывать методы 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!
Действительно отличное решение. Я создал простое расширение для ServiceBase [], как предложил Дэвид, которое позволяет запускать службы всего одной строкой кода: pastebin.com/F0fhhG2R
@Funbit Это действительно здорово - не могли бы вы, если бы я опубликовал это в своем блоге в качестве обновления к пошаговой инструкции?
У меня возникла проблема, когда работа в интерактивном режиме мешает мне отправлять служебные команды через ServiceController. Если у меня запущена служба с именем «MyService», а затем я пытаюсь отправить команду службы, например: (new ServiceController («MyService»)). ExecuteCommand (160); Это не удается, потому что ServiceController возвращает нуль в интерактивном режиме и работает только при работе в качестве службы. затрудняет отладку выполняемых служебных команд.
+1 Мой бывший коллега создал базовый класс EasyRunService (наследующий ServiceProcess), который делает почти то же самое, но без необходимости отражения (потому что OnStart теперь находится в базовом классе). Это действительно упрощает отладку службы Windows.
У меня нет консоли, использующей решение @Funbit.
Изменение вывода на консольное приложение изменяет установку моего приложения или?
@ Chazt3n Убедитесь, что тип вывода вашего проекта установлен на «Консольное приложение». Что касается установки службы, не имеет значения, какой тип вывода выбран, поведение одинаковое.
Мне не удалось установить в качестве службы Windows с выбранным CApp, вместо этого я изменил код, ждите навсегда
Тем не менее отличное решение! Единственное, что я бы добавил (как показано в 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
+1 Отличное решение (Windows Service - .NET 4.0). Благодарю @Funbit за его методы расширения для ServiceBase в соответствии с его комментарием выше!
человек ... вы - босс ... также полностью согласен с @ArvoBowen, что нам нужно изменить тип вывода на приложение Console, иначе Console.ReadKey () выдаст исключение и обслуживание будет остановлено.
Иногда важно проанализировать, что происходит. во время запуска службы. Присоединение к процессу здесь не помогает, потому что вы недостаточно быстро присоединяете отладчик во время запуска службы.
Короткий ответ: для этого я использую следующий 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». появиться. Нажмите IG666 Yes, debug Servicename.exe, как показано на скриншоте: 
Впоследствии, особенно в Windows 7, UAC может предложить вам ввести учетные данные администратора. Введите их и продолжайте с Yes:

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

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

Нажатие F5 немедленно продолжает выполнение,, пока не будет достигнута следующая подготовленная вами точка останова.
Намекать: Чтобы служба продолжала работать, выберите Отладка -> Отключить все. Это позволяет запускать клиент, взаимодействующий со службой после того, как она правильно запустилась и вы закончили отладку кода запуска. Если вы нажмете Shift + F5 (остановить отладку), это прекратит работу службы. Вместо этого вы должны использовать Панель управления сервисом, чтобы остановить его.
Примечание, что
Если вы создаете Выпускать,, тогда код отладки автоматически удаляется и служба работает нормально.
Я использую Debugger.Launch(), а запускает и подключает отладчик. Я также протестировал Debugger.Break(), который не работало, потому что при запуске службы еще не подключен отладчик (вызывающий «Ошибка 1067: процесс неожиданно завершен».).
RequestAdditionalTime устанавливает более длинный тайм-аут для запуска службы (это нет задерживает сам код, но немедленно продолжит выполнение инструкции Debugger.Launch). В противном случае тайм-аут по умолчанию для запуска службы будет слишком коротким, и запуск службы завершится неудачно, если вы не вызовете base.Onstart(args) достаточно быстро из отладчика. Практически 10-минутный тайм-аут позволяет избежать появления сообщения «служба не ответила ... "» сразу после запуска отладчика.
Когда вы к нему привыкнете, этот метод станет очень простым, потому что он просто требует, чтобы вы добавили добавить 4 строки к существующему сервисному коду, что позволяет быстро получить контроль и отладить.
Из любопытства знаете ли вы, есть ли тайм-аут для взаимодействия пользователя с пользовательской подсказкой Debugger.Launch ()?
Как описано, base.RequestAdditionalTime(600000) предотвратит завершение службы управления службой в течение 10 минут, если она не вызовет base.OnStart(args) в течение этого промежутка времени). Кроме того, я помню, что UAC также прервется, если вы не введете учетные данные администратора через некоторое время (я не знаю, сколько именно секунд, но я думаю, вам нужно ввести их в течение минуты, иначе UAC прервется) , что завершит сеанс отладки.
Я обнаружил, что это лучший метод отладки сообщений CustomCommand. +1.
Используйте библиотеку Верхняя полка.
Создайте консольное приложение, затем настройте настройку в главном
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.
Их лицензирование было слишком запутанным, чтобы понять
Они используют Apache License afaik. Topshelf - это самый простой способ, который я использовал для разработки и отладки служб Windows. Очень проста в использовании. Разрабатывать как консольное приложение. Установить как службу с одним переключателем командной строки. Настоятельно рекомендуется.
TopShelf сэкономил мне массу времени. Спасибо
Этот Видео на YouTube Фабио Скопеля объясняет, как довольно хорошо отлаживать службу Windows ... Фактический способ выполнения этого начинается в 4:45 на видео ...
Вот код, описанный в видео ... в вашем файле Program.cs добавьте материал для раздела Debug ...
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()
{
}
How it works
По сути, вам нужно создать 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 запустит логику
Я искал этот ответ, не знаю, почему его так низко оценили. Объяснил код, чтобы помочь другим, или, возможно, больше комментариев;)
Для устранения неполадок в существующей программе службы Windows используйте Debugger.Break (), как предлагали другие ребята.
Для новой программы Windows Service я бы предложил использовать метод Джеймса Майкла Хэра http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template-redux.aspx
У вас есть два варианта отладки.
Пожалуйста, обратитесь к сообщению в блоге ЭТО, которое я создал для этой темы.
Просто положите свой обеденный отладчик куда угодно и прикрепите Visualstudio при запуске
#if DEBUG
Debugger.Launch();
#endif
Также вам нужно запустить VS от имени администратора и разрешить автоматическую отладку процесса другим пользователем (как объяснено здесь):
reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
Используйте проект C# шаблона службы Windows для создания нового приложения службы https://github.com/HarpyWar/windows-service-template
Есть автоматическое определение консольного / сервисного режима, автоматический установщик / деинсталлятор вашей службы и несколько наиболее часто используемых функций.
Вот простой метод, который я использовал для тестирования службы, без каких-либо дополнительных методов «отладки» и со встроенными модульными тестами VS.
[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 });
}
Просто вставьте
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();, когда вы запустите свою программу.
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
}
}
это проще. просто измените настройку конфигурации решения на отладку, запустите проект / решение, добавьте точки останова по мере продвижения.
Лучшим вариантом является использование пространства имен «Система. Диагностика».
Включите свой код в блок 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
Я создал этот билет User Voice. Считайте голосование за это: visualstudio.uservoice.com/forums/121579-visual-studio-ide/…