如何调试 Windows 服务而不至于失败






3.86/5 (20投票s)
一种调试 Windows 服务任何部分的方法。
引言
Windows 服务是我们使用的 Windows 操作系统提供的强大编程工具,它可以在无需用户登录系统的情况下运行程序。
由于 Windows 服务的特性,Visual Studio 无法直接启动服务并对其进行调试。同时,您也无法附加调试器来调试服务的构造函数或 Start
事件。这是因为您无法附加一个尚不存在的进程!
存在多种解决方案:其中一种由 Lee Humphries 在一篇精彩的文章中进行了阐述。但是,如何将调试器附加到我们想要开始调试的程序点呢?嗯,在 .NET 2.0 中是可以做到的,您只需要使用 System.Diagnostic
命名空间中的 Debugger
类。
背景
System.Diagnostic 中的 Debugger 类有一个对我们而言非常重要的方法:Debugger.Launch()
。
当 Debugger.Launch()
执行时,它会检查当前进程是否已附加到任何调试器;如果没有,它将打开调试器附加窗口,并提示我们选择要与程序一起使用的合适调试器。然后,您只需要将 Launch()
的调用定位到您希望开始控制服务的代码位置即可。
请参阅下面的代码,这是一个在 Windows 服务 OnStart
事件中初始化调试器的示例
protected override void OnStart(string[] args)
{
iTest = 1;
#if (DEBUG)
Debugger.Launch(); //<-- Simple form to debug a web services
#endif
timer1.Enabled = true;
}
当框架执行 Debugger.Launch
方法并提示您选择调试器时,请选择显示服务代码的 VS 实例,然后继续在调试器的控制下运行服务。
您需要将该指令用 #if #endif
子句括起来,因为 Debugger.Launch()
方法也会在 Release 模式下执行(这本不应该发生,但 .NET 2.0 在 Debugger.Launch()
方法中存在一个 bug)。
使用代码
- 下载并编译文章中附带的带有 DEBUG 选项的代码。
- 安装 Windows 服务。我建议自动化此任务。我个人在工具 -> 外部工具菜单中创建了两个输入:一个用于安装,另一个用于卸载服务。请参见下图
- Title: InstallService
- Command: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe (使用您的 Windows 安装目录)
- Argument: WServiceDebug.exe
- Initial Directory: $(ProjectDir)/bin/debug
- Title: UnInstallService
- Command: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe (使用您的 Windows 安装目录)
- Argument: /u WServiceDebug.exe
- Initial Directory: $(ProjectDir)/bin/debug
- 在 Visual Studio 中,请确保 Web 服务代码页已打开。
- 启动服务。打开服务小程序:控制面板 -> 管理工具 -> 服务。您将看到名为 WServiceDebug 的服务尚未启动。右键单击并选择启动。您将看到打开了选择调试器的对话框。选择已打开 Windows 服务项目的 Visual Studio 实例。转到 Visual Studio,您将看到程序已停止,准备进行调试。按 F5,您将在输出窗口中看到计时器每 5 秒写入整数值。不要启动新的调试器;请使用已编译该服务的 Visual Studio 实例。
- 在 Stop 过程中设置一个断点并停止服务。您将看到程序在断点处停止,按 F5 结束调试会话。
- 卸载 Windows 服务(使用第 3 点中创建的快捷方式)。然后,在 Release 模式下重新编译应用程序。然后,重新安装 Windows 服务并启动它(您必须修改快捷方式以安装/卸载到初始目录:$(ProjectDir)/bin/release。您将看到调用调试器将不会成功,服务将正常启动。
- 在 Debug 模式下重新编译程序,并尝试在服务代码中的
Launch()
方法的各种情况下进行实验。
代码是一个简单的 Windows 服务,它使用一个计时器每 5 秒递增一个整数值。该服务将整数变量的值写入输出窗口。请查看代码中的 Launch()
方法。
如果您有其他系统来安装/卸载服务,请跳过以下说明
要为示例 Windows 服务创建安装条目,请单击工具 -> 外部工具 -> 添加,然后输入
要为示例 Windows 服务创建卸载条目,请单击工具 -> 外部工具 -> 添加,然后输入
关注点
使用 System.Debugger.Launch()
方法是解决调试 Windows 服务问题的简单解决方案。我猜想你们中的许多人都在使用这种技术,但我没有找到太多关于这方面的信息(我也没做太多研究)。
历史
- 2007 年 8 月 7 日 - 初始版本。