From Vista onwards all the services run in Session 0, and session 0 has no interaction with desktop, this is named as session isolation and was added for security reason to windows. This brings a problem when we try to debug a service start up from a user session, if the service is already running one can attach the debugger and start debugging it, but attaching the debugger at startup becomes a problem.
Image File Execution option is the way to go:
- Run regedit.exe
- Goto HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
- Create a new key for your service executable (example: myService.exe)
- Create a new string value under your exe. The name of the string value is 'Debugger', and the value is debugger path like 'c:\debuggers\windbg.exe'
There still is a problem with this, when the service starts it will be started under debugger but you wont be able to see the debugger because it runs in session 0 and session 0 has no interaction with desktop. There are two ways to solve this problem:
1. Change the services properties and allow it to interact with desktop. This can be done from registry or services.msc-> service Properties or can be passed as an argument in CreateService API. However some services might not be happy if you change their property, in that case you should chose second option.
2. Second option is to configure remote debugger session. While setting the registry for IFEO as above, add the command line parameter -Server TCP:Port=<ANY PORT> to windbg.exe. (e.g. "C:\debugger\Windbg.exe" -server tcp:port=5555). Doing so will not only start the service under debugger but also start a server session for windbg, that can be connected from user session. Now from any user session you can start windbg and connect to the session 0 debugger using 'Connect to a remote session ' option in windbg.
Before you can happily debug the service now, you need overcome one last problem. And the problem is services timeout, if you start debugging the service you will find that after 30 seconds service is automatically killed and you can't debug after that. So who killed the service? Answer is SCM. SCM starts the service and expects that service should signal within 30 seconds that it is running happily, if the service doesn't respond within that time(which it ofcourse will not, if you are debugging it from its startup), SCM assumes that something bad(like a hang or crash) happened with the service, and it will terminate the service. So the solution to this problem is to increase the timeout from 30 seconds to some other good value that is long enough for you to debug the service.
To increase the timeout, create a new DWORD value ServicePipeTimeout under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control, and set a new timeout value. SCM reads the value as in miliseconds. You would need to restart the machine inorder to make the setting effective. Make sure that you revert back the timeout value once you are done with debugging because this is a global setting and is applicable to all the services.