在排查服务启动时错误的时候, debugger会运行在后台, 我们无法与之交互. 因为服务是运行在一个不同的winstation里的, 这意味着我们不能通过desktop与它们交互. 这也意味着, 已经加载了的debugger即使在运行, 也是运行在后台, 我们无法与它交互.
解决方案是进入services.msc, 找到这个服务的属性, 让它使用local system账号运行, 然后勾选选项"allow interact with the desktop".
但是, IIS的工作者进程worker process与服务进程一样, 都是在后台诞生的, 要命的是, 我们没有机会去勾选什么allow interact with the desktop. 这意味着debugger也会在后台被加载, 我们还是无法与它交互.
解决方案不止一种, 但是下面这种比较有趣.
cdb.exe和windbg.exe都能够创建TCP sockets(或者说是named pipes connection), 然后监听它们, 这样前台的debugger就能够连接到后台被debug的进程的debugger上, 它们共享一个debugging session. 这里我们就用这种socket的特性来在后台的winstation和w3wp.exe一起的debugger和前台的debugger之间创建一个隧道.
让我们一步一步来:
第一步:
设置应用程序image的执行选项, 从而允许在这个image的实例诞生的时候, 我们的第一个debugger能够附着到worker process上.
要做到这一点, 我们需要在注册表中创建下面的键值对:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\w3wp.exe
SZ Debugger = “c:\debuggers\cdb.exe –cf c:\debuggers\cmds.txt”
这里假设, 你的Debugging Tools For Windows安装在c:\debuggers文件夹.
第二步:
配置debugger自动地开启一个socket供以后使用.
注意上面cdb.exe命令行中的 "-cf " 选项, 它会告诉cdb.exe在debugger刚刚attach到目标进程的时候, 从某个指定的文件中读取并执行一些初始化的命令. 所以我们需要创建一个叫做cmds.txt的文本文件, 把它放在c:\debuggers目录下. 这个文件的内容是像下面这样的.
.logopen c:\debuggers\debugging.log
.server tcp:port=9999
g
保存文件. 关于debugger使用的这些命令, 请查看下面的说明.
.logopen - 任何在这个debugging session中发生的事情都会记录在这个新开启的日志文件中.
.server tcp:port=9999 - 监听在9999端口上的TCP Socket.
g - 继续执行
第三步:
开启应用程序池, 并发送个它至少一个请求.
当w3wp.exe进程创建出来之后, 你就能够通过任务管理器看出来你同时还有cdb.exe也在运行, 但是你不能直接的访问它.
第四步:
运行你的第二个debugger, 并连接到Socket上.
运行WinDGB.exe, 并传递给它一个像下面命令这样的-remote参数:
Windbg.exe -remote tcp:Port=9001,Server=MYSERVER
上面的MYSERVER应该被你的机器名所取代.
搞定啦~~~ windbg.exe已经连接到有cdb.exe创建出来的socket上了, 你现在可以从头开始对你w3wp.exe进行live debug了!
祝你debugging愉快~
翻译自:
How to attach a debugger from the creation time of the Worker Process (w3wp.exe)