Можно ли отлаживать службы Windows в Visual Studio?
Я использовал код вроде
System.Diagnostics.Debugger.Break();
но он дает некоторую ошибку кода, например:
Я получил две ошибки события: eventID 4096 VsJITDebugger и «Служба не ответила на запрос запуска или управления своевременно».
Вы также можете попробовать это.
(После долгих поисков я нашел это в разделе «Как отлаживать службы Windows в Visual Studio».)
источник
Вы должны выделить весь код, который будет делать что- то из проекта службы, в отдельный проект, а затем создать тестовое приложение, которое можно будет запускать и отлаживать в обычном режиме.
Сервисный проект будет лишь оболочкой, необходимой для реализации сервисной части.
источник
Либо это, как было предложено Лассе В. Карлсеном, либо настройте цикл в своей службе, который будет ждать подключения отладчика. Самый простой - это
while (!Debugger.IsAttached) { Thread.Sleep(1000); } ... continue with code
Таким образом, вы можете запустить службу, а внутри Visual Studio выбрать «Присоединить к процессу ...» и присоединиться к своей службе, которая затем возобновит нормальное выполнение.
источник
if (Environment.UserInteractive) { InteractiveRun(args); } else { Service instance = new Service(); ServiceBase[] servicesToRun = new ServiceBase[] { instance }; ServiceBase.Run(servicesToRun); }
Start
/OnStart()
я думаюfoo(bar)
Учитывая, что у
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
потоки фальшивой службы работают, это не приведет к завершению процесса.источник
Статья 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» при отладке, перекомпилируйте и установите службу.
источник
Можно сделать консольное приложение. Я использую эту
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
).источник
ServiceBase
).». Мне легче отлаживать консольное приложение, но я понимаю, если это не убедит всех.Я использую отличный пакет Nuget под названием ServiceProcess.Helpers.
И цитирую ...
Он помогает отладить службы Windows, создавая пользовательский интерфейс воспроизведения / остановки / паузы при работе с подключенным отладчиком, но также позволяет устанавливать и запускать службу в среде сервера Windows.
Все это с помощью одной строчки кода.
http://windowsservicehelper.codeplex.com/
После установки и подключения все, что вам нужно сделать, это установить проект службы Windows в качестве начального проекта и нажать кнопку «Пуск» в отладчике.
источник
Вы также можете попробовать метод System.Diagnostics.Debugger.Launch () . Это помогает переместить указатель отладчика в указанное место, и вы сможете отлаживать код.
Перед этим шагом установите service.exe с помощью командной строки командной строки Visual Studio - installutil projectservice.exe.
Затем запустите свою службу из Панели управления -> Администрирование -> Управление компьютером -> Служба и приложение -> Службы -> Имя вашей службы.
источник
Я просто добавил этот код в свой класс обслуживания, чтобы косвенно вызвать OnStart, аналогично OnStop.
public void MyOnStart(string[] args) { OnStart(args); }
источник
Я использую
/Console
параметр в проекте Visual Studio Debug → Start Options → Command line arguments :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() {....} }
источник
Я нашел этот вопрос, но думаю, что нет четкого и простого ответа.
Я не хочу присоединять свой отладчик к процессу, но я все равно хочу иметь возможность вызывать службу
OnStart
иOnStop
методы. Я также хочу, чтобы он запускался как консольное приложение, чтобы я мог записывать информацию из NLog в консоль.Я нашел эти блестящие руководства, которые делают это:
Отладка проекта службы Windows
Более простой способ отладки службы Windows
Начните с изменения проектов
Output type
наConsole Application
.Измените свой,
Program.cs
чтобы он выглядел так:static class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main() { // Startup as service. ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new Service1() }; if (Environment.UserInteractive) { RunInteractive(ServicesToRun); } else { ServiceBase.Run(ServicesToRun); } } }
Затем добавьте следующий метод, чтобы службы могли работать в интерактивном режиме.
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); }
источник
К сожалению, если вы пытаетесь отладить что-либо в самом начале работы службы Windows, «присоединение» к запущенному процессу не сработает. Я пробовал использовать Debugger.Break () в процедуре OnStart, но в 64-битном приложении, скомпилированном в Visual Studio 2010, команда break просто выдает такую ошибку:
System error 1067 has occurred.
На этом этапе вам необходимо настроить параметр «Выполнение файла образа» в вашем реестре для исполняемого файла. На настройку уходит пять минут, и работает она очень хорошо. Вот статья Microsoft, в которой приведены подробности:
Как: запустить отладчик автоматически
источник
Попробуйте собственную командную строку для событий после сборки в Visual Studio .
Попробуйте добавить это в пост-сборку:
@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 applications that maybe using the service including services.msc and Windows event log. 1058 -- Can't be started because disabled or has no enabled associated devices → just delete it. 1060 -- Doesn't exist → just delete it. 1062 -- Has not been started → just delete it. 1053 -- Didn't respond to start or control → see event log (if logged to event log). It may be the service itself throwing an exception. 1056 -- Service is already running → stop the service, and 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должно быть достаточно его отладки.
источник
В
OnStart
методе делаем следующее.protected override void OnStart(string[] args) { try { RequestAdditionalTime(600000); System.Diagnostics.Debugger.Launch(); // Put breakpoint here. .... Your code } catch (Exception ex) { .... Your exception code } }
Затем запустите командную строку от имени администратора и введите следующее:
Вышеупомянутая строка создаст test-xyzService в списке служб.
Чтобы запустить службу, вам будет предложено подключиться к дебюту в Visual Studio или нет.
Чтобы остановить службу:
Чтобы удалить или удалить:
источник
Отладка службы Windows через http (протестировано с VS 2015 Update 3 и .Net FW 4.6)
Во-первых, вы должны создать консольный проект в своем решении VS (Добавить -> Новый проект -> Консольное приложение).
В новом проекте создайте класс ConsoleHost с этим кодом:
class ConsoleHost : IDisposable { public static Uri BaseAddress = new Uri(http://localhost:8161/MyService/mex); private ServiceHost host; public void Start(Uri baseAddress) { if (host != null) return; host = new ServiceHost(typeof(MyService), baseAddress ?? BaseAddress); //binding var binding = new BasicHttpBinding() { Name = "MyService", MessageEncoding = WSMessageEncoding.Text, TextEncoding = Encoding.UTF8, MaxBufferPoolSize = 2147483647, MaxBufferSize = 2147483647, MaxReceivedMessageSize = 2147483647 }; host.Description.Endpoints.Clear(); host.AddServiceEndpoint(typeof(IMyService), binding, baseAddress ?? BaseAddress); // Enable metadata publishing. var smb = new ServiceMetadataBehavior { HttpGetEnabled = true, MetadataExporter = { PolicyVersion = PolicyVersion.Policy15 }, }; host.Description.Behaviors.Add(smb); var defaultBehaviour = host.Description.Behaviors.OfType<ServiceDebugBehavior>().FirstOrDefault(); if (defaultBehaviour != null) { defaultBehaviour.IncludeExceptionDetailInFaults = true; } host.Open(); } public void Stop() { if (host == null) return; host.Close(); host = null; } public void Dispose() { this.Stop(); } }
А это код класса Program.cs:
public static class Program { [STAThread] public static void Main(string[] args) { var baseAddress = new Uri(http://localhost:8161/MyService); var host = new ConsoleHost(); host.Start(null); Console.WriteLine("The service is ready at {0}", baseAddress); Console.WriteLine("Press <Enter> to stop the service."); Console.ReadLine(); host.Stop(); } }
Такие конфигурации, как строки подключения, следует скопировать в файл App.config проекта консоли.
Чтобы запустить консоль, щелкните правой кнопкой мыши проект консоли и выберите «Отладка» -> «Начать новый экземпляр».
источник
Просто добавьте подрядчика в свой класс обслуживания (если у вас его еще нет). Ниже вы можете проверить и посмотреть пример для Visual Basic .net.
Public Sub New() OnStart(Nothing) End Sub
После этого щелкните проект правой кнопкой мыши и выберите « Отладка -> Начать новый экземпляр ».
источник