调试Windows服务
这个问题在使服务成为控制台/服务混合体方面有一个很好的答案。请参阅用户marc_s的答案。我不想在这里重复答案。
问题的原因:无法直接调试Windows服务,因为服务是在后台运行的,无法显示控制台窗口。
解决方法:将服务设置为控制台/服务混合体,这样可以在调试时显示控制台窗口。
下面是使用C#的示例代码,演示如何将服务设置为控制台/服务混合体:
using System; using System.ServiceProcess; namespace MyService { static class Program { static void Main() { if (Environment.UserInteractive) { MyService service = new MyService(); service.StartService(); Console.WriteLine("Press any key to stop the service..."); Console.ReadKey(); service.StopService(); } else { ServiceBase.Run(new MyService()); } } } public class MyService : ServiceBase { protected override void OnStart(string[] args) { // TODO: 在服务启动时执行必要的操作 } protected override void OnStop() { // TODO: 在服务停止时执行必要的操作 } public void StartService() { OnStart(null); } public void StopService() { OnStop(); } } }
使用上述代码,可以在控制台环境中调试Windows服务。
问题原因:在代码中,通过判断是否为用户交互模式来决定是以控制台应用程序的方式运行还是以Windows服务的方式运行。当以控制台应用程序方式运行时,可以通过命令行参数来执行不同的操作,如安装服务、卸载服务或以交互模式运行服务。而当不是用户交互模式时,直接以Windows服务的方式运行。
解决方法:通过判断是否为用户交互模式来决定以何种方式运行服务,以便方便地运行和调试服务,并且可以不使用InstallUtil程序来安装和卸载服务。
对于大多数情况来说,将服务作为控制台应用程序运行已经足够了。为了实现这一点,通常我会有以下的启动代码:
private static void Main(string[] args) { if (Environment.UserInteractive) { Console.WriteLine("My Service"); Console.WriteLine(); switch (args.FirstOrDefault()) { case "/install": ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location}); break; case "/uninstall": ManagedInstallerClass.InstallHelper(new[] {"/u", Assembly.GetExecutingAssembly().Location}); break; case "/interactive": using (MyService service = new MyService(new ConsoleLogger())) { service.Start(args.Skip(1)); Console.ReadLine(); service.Stop(); } break; default: Console.WriteLine("Supported arguments:"); Console.WriteLine(" /install Install the service"); Console.WriteLine(" /uninstall Uninstall the service"); Console.WriteLine(" /interactive Run the service interactively (on the console)"); break; } } else { ServiceBase.Run(new MyService()); } }
这样不仅可以方便地运行和调试服务,而且还可以在不需要使用InstallUtil程序的情况下进行安装和卸载。
(完)
文章标题:调试Windows服务的问题及解决方法
在Windows服务的开启方法(OnStart)中,使用以下代码:
#if DEBUG if(!System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Launch(); #endif
这样做会弹出"Just in Time Debugger",然后可以附加一个调试器。
非常感谢!! 🙂 弹出"Just in Time Debugger"之后,我可以附加一个调试器 :)
我希望我也能这样做,但是我声望不够。另外,你怎样接受一个答案?
你会在左边下方看到一个勾号,点击它即可。
还可以帮我解决这个问题吗:我们每次修改Windows服务时都需要重新安装吗?还是仅构建就足够了?
在大多数情况下,仅构建就足够了。但并非总是如此。为了简化回答:如果你没有看到修改生效,请重新安装。