如何调试 Windows 服务
概要
本文分步介绍了如何使用 WinDbg 调试程序 (windbg.exe) 调试 Windows 服务。 要调试 Windows 服务,可以在服务启动后将 WinDbg 调试程序附加到托管该服务的进程,或者可以配置服务以在启动时附加 WinDbg 调试程序,以便解决与服务启动相关的问题。 本文将介绍这两种方法。
服务启动后将 WinDbg 调试程序附加到服务
此方法与你用于将调试程序附加到进程然后调试进程的方法类似。
使用托管要调试服务的进程的进程 ID
- 若要确定托管要调试服务的进程的进程 ID (PID),请使用以下任一方法。
方法 1: 使用任务管理器
- 右键单击任务栏,然后单击
“任务管理器”。 随即显示“Windows 任务管理器”对话框。 - 单击“Windows 任务管理器”对话框的
“进程”选项卡。 - 在“映像名称”下,单击托管要调试服务的进程的映像名称。 请注意,此进程的进程 ID 是由
相应的 PID 字段值指定的。
- 右键单击任务栏,然后单击
方法 2: 使用任务列表实用工具 (tlist.exe)
- 单击“开始”,然后单击
“运行”。 随即出现“运行”对话框。 - 在“打开”框中,键入
cmd,然后单击“确定”。 - 在命令提示符处,更改目录路径以显示计算机上的 tlist.exe 文件位置。
注意 tlist.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows - 在命令提示符处,键入
tlist 以列出计算机上当前运行的所有进程的映像名称以及进程 ID。
注意 请记下托管要调试服务的进程的进程 ID。
- 单击“开始”,然后单击
- 在命令提示符处,更改目录路径以显示计算机上的 windbg.exe 文件位置。
注意 如果命令提示符未打开,请按照方法 1 的步骤 a 和 b 操作。 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。 - 在命令提示符下,键入 windbg –p
ProcessID /g 以将 WinDbg 调试程序附加到托管要调试服务的进程。
注意 ProcessID 是托管要调试服务进程的进程 ID 的占位符。
使用托管要调试服务的进程的映像名称
只能在托管要运行服务的进程正好存在一个正在运行的实例时使用此方法。 为此,请按照下列步骤操作:
- 单击“开始”,然后单击
“运行”。 随即出现“运行”对话框。 - 在“打开”框中,键入
cmd,然后单击“确定”以打开命令提示符。 - 在命令提示符处,更改目录路径以显示计算机上的 windbg.exe 文件位置。
注意 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。 - 在命令提示符下,键入 windbg –pn
ImageName /g 以将 WinDbg 调试程序附加到托管要调试服务的进程。
注意 ImageName 是托管要调试服务进程的映像名称的占位符。 “-pn”命令行选项指定
ImageName 命令行参数是进程的映像名称。
启动 WinDbg 调试程序并附加到托管要调试服务的进程
- 启动 Windows 资源管理器。
- 找到计算机上的 windbg.exe 文件。
注意 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows - 同时运行 windbg.exe 文件和 /g 命令行开关以启动 WinDbg 调试程序。 设置断点后,/g 命令行开关允许跟踪的进程继续运行。
- 在“文件”菜单中,单击“附加到进程”以显示“附加到进程”对话框。
- 单击以选择托管要调试服务的进程相应节点,然后单击
“确定”。 - 在出现的对话框中,单击“是”以保存工作区基本信息。 请注意,现在你可以调试服务的反汇编代码。
配置服务以在启动时附加 WinDbg 调试程序
如果要解决与服务启动相关的问题,可以使用此方法调试服务。
配置“映像文件执行”选项。 为此,请使用下列方法之一:
方法 1: 使用全局标志编辑器 (gflags.exe)
- 启动 Windows 资源管理器。
找到计算机上的 gflags.exe 文件。
注意 gflags.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。
运行 gflags.exe 文件以启动全局标志编辑器。
在“映像文件名称”文本框中,键入托管要调试服务的进程的映像名称。 例如,如果要调试由映像名称为 MyService.exe 的进程托管的服务,请键入
MyService.exe。
在“目标”下,单击以选中“映像文件选项”选项。
在“映像调试程序选项”下,单击以选中“调试程序”复选框。
在“调试程序”文本框中,键入要使用的调试程序的完整路径。 例如,如果要使用 WinDbg 调试程序来调试服务,可以键入与以下路径相似的完整路径: C:\Program Files\Debugging Tools for Windows\windbg.exe。单击“应用”,然后单击,“确定”退出全局标志编辑器。
方法 2: 使用注册表编辑器
- 单击“开始”,然后单击
“运行”。 随即出现“运行”对话框。 - 在“打开”框中,键入
regedit,然后单击“确定”以启动注册表编辑器。 - 重要说明
本部分(或称方法或任务)包含有关如何修改注册表的步骤。 但是,注册表修改不当可能会出现严重问题。 因此,请务必严格按照这些步骤操作。
为了获得进一步的保护,请在修改注册表之前对其进行备份。 这样就可以在出现问题时还原注册表。
有关如何备份与还原注册表的详细信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
322756 如何在 Windows 中备份和还原注册表在注册表编辑器中,找到并右键单击下面的注册表子项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
- 指向“新建”,然后单击
“项”。 在注册表编辑器的左侧窗格中,注意已选中“新项 #1”(新注册表子项的名称)用于编辑。 - 键入 ImageName 以替换“新项 #1”,然后按 ENTER。
注意 ImageName 是托管要调试服务的进程的映像名称的占位符。 例如,如果要调试由映像名称为 MyService.exe 的进程托管的服务,请键入MyService.exe。 - 右键单击在步骤 e 中创建的注册表子项。
- 指向“新建”,然后单击“字符串值”。 在注册表编辑器的右侧窗格中,注意已选中“新值 #1”(新注册表项的名称)用于编辑。
- 将“新值 #1”替换为“调试程序”,然后按 ENTER。
- 右键单击在步骤 h 中创建的“调试程序”注册表项,然后单击“修改”。 将出现“编辑字符串”对话框。
- 在“数值数据”文本框中,键入
DebuggerPath,然后单击“确定”。
注意 DebuggerPath 是要使用的调试程序完整路径的占位符。 例如,如果要使用 WinDbg 调试程序来调试服务,可以键入与以下路径相似的完整路径:C:\Progra~1\Debugg~1\windbg.exe - 为了让桌面上出现调试程序窗口以及与调试程序交互,请使你的服务可进行交互。 如果你的服务无法进行交互,调试程序将启动,但是你无法看见该调试程序且无法发出命令。 若要使你的服务可进行交互,请使用以下方法之一:
方法 1: 使用“服务”控制台
- 单击“开始”,然后指向“程序”。
- 在“程序”菜单上,指向“管理工具”,然后单击“服务”。 随即显示“服务”控制台。
- 在“服务”控制台右侧窗格中,右键单击“ServiceName”,然后单击“属性”。
注意 ServiceName 是要调试的服务名称的占位符。
方法 2: 使用注册表编辑器
- 在注册表编辑器中,找到并单击下面的注册表子项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName注意将 ServiceName 替换为要调试的服务的名称。 例如,如果要调试名为 MyService 的服务,请找到并单击以下注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService
- 在注册表编辑器右窗格中的“名称”字段下,右键单击“类型”,然后单击“修改”。 随即出现“编辑 DWORD 值”对话框。
- 将“数值数据”文本框中的文本更改为将当前文本的二进制值和二进制值 0x00000100 作为两个操作数的二进制 OR 操作的结果。 二进制值 0x00000100 对应于计算机上 WinNT.h 头文件中定义的 SERVICE_INTERACTIVE_PROCESS 常量。 此常量指定服务本身具备交互性。
- 服务启动时,该服务与服务控制管理器通信,告知该服务必须启动多长时间(服务的超时时间)。
如果服务控制管理器未在超时时间内收到来自服务的“服务已启动”通知,服务控制管理器将终止托管该服务的进程。 此超时时间通常少于 30 秒。
如果未调整此超时时间,服务控制管理器就会在你尝试调试时终止进程和附加的调试程序。 要调整此超时时间,请按照下列步骤操作:
- 在注册表编辑器中,找到并右键单击下面的注册表子项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
- 指向“新建”,然后单击“DWORD 值”。 在注册表编辑器的右侧窗格中,注意
已选中“新值 #1”(新注册表项的名称)用于编辑。 - 键入 ServicesPipeTimeout 以替换“新值 #1”,然后按 ENTER。
- 右键单击在步骤 c 中创建的“ServicesPipeTimeout”注册表项,然后单击“修改”。 随即出现“编辑 DWORD 值”对话框。
- 在“数值数据”文本框中,键入 TimeoutPeriod,然后单击“确定”
注意 TimeoutPeriod 是你要为服务设置的超时时间(以毫秒为单位)值的占位符。 例如,如果要将超时时间设置为 24 小时(86400000 毫秒),请键入 86400000。 - 重启计算机。 必须重启计算机才能使服务控制管理器应用此更改。
- 在注册表编辑器中,找到并右键单击下面的注册表子项:
- 启动 Windows 服务。 为此,请按照下列步骤操作:
- 单击“开始”,然后指向“程序”。
- 在“程序”菜单上,指向“管理工具”,然后单击
“服务”。 随即显示“服务”控制台。 - 在“服务”控制台右侧窗格中,右键单击 ServiceName,然后单击“启动”。注意 ServiceName 是要调试的服务名称的占位符。
疑难解答
在你尝试跨网络调试服务之前,请确保可从运行服务的计算机上访问该服务所用的符号和源文件。 为此,请使用下列方法之一:
- 至少授予所有人对计算机上的文件夹(包含服务使用的符号和源文件)的读取访问权限。
- 将服务使用的这些符号和源文件复制到运行该服务的计算机上。