If you are like me working on server development you may run into the situation that a service fails early during startup, i.e. within the first couple of seconds. You’ll soon realize that manually attaching a debugger doesn’t work well, if at all. Even if you’ll be running
windbg -pn MyService.exe
you may not actually be fast enough. Or there are multiple instances of that image running (e.g. SvcHost.exe) and the above command becomes kind of useless. Now if you have been reading the ‘Debugging Tools for Windows’ documentation (or have debugged services before) you’ll already know what I am about to tell you here.
As I mentioned above, the first problem you’re fighting with is that the failure happens very early. Another problem you may have is that your service is running e.g. as ‘NT AUTHORITY\NETWORK SERVICE’ and thus may not be able to interact with your desktop. But Windows’ right here to help you out with ‘Image File Execution Options’. This basically allows you to execute a command when a particular image is being executed.
You start by creating a key for the image file in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\MyService.exe
There you create a new string value of the name ‘Debugger’ and set its value to the path of the debugger you want to invoke, e.g. something like ‘C:\Debuggers\cdb.exe’. To mitigate the problem of the non-interactive service, you’ll probably want to use the debugger remotely, so you’ll create a debugging server: ‘C:\Debuggers\cdb.exe -server npipe:pipe=MyDebuggingSession’. What you have now is a debugger which is attached as soon as the service starts and which is accessible remotely. Thus, you can either on the server itself or another machine which has access run for instance
windbg -remote npipe:server=my-machine,pipe=MyDebuggingSession
and there you go: you are now debugging the service. Use the various command line options for the debuggers to
- ignore the initial break point (-g)
- run commands right after the debugger is attached (-c)
- create a script which sets some useful breakpoints and run it when the debugger is attached (e.g. -c “$<MyScript.txt”)
You may actually have to adjust the service control timeout. To do so, add a DWORD called ‘ServicesPipeTimeout’ to the registry key
and set its value to the number of milliseconds you want the service to wait before timing out.
You’ll find pretty much all of this information also in the help file for ‘Debugging Tools for Windows’ under ‘Debugging a Service Application’. Enjoy!