Debugging a service is a bit more tricky than debugging a normal application for several reasons. First, the debugger cannot start the service; the SCM must start the service. Second, many services start before a user logs on to the machine. For this reason, setting an automatic service to manual while you're debugging it is a good idea. Third, services run in their own window station and desktop, which is not visible to an interactive user.
So how can you debug a service? The best way is to run it as a regular executable instead of as a service. Inside your service's (w)main or (w)WinMain function, check for a special command-line switch of your own devising and, if this switch is present, call your service's ServiceMain function directly instead of calling StartServiceCtrlDispatcher. This technique, of course, has several disadvantages:
The approach just described makes debugging your service very easy, but a better approach is to connect a debugger to the service while the service is running. Most debuggers offer the ability to connect to a process while it is running. If you already have a debugger installed on your system, you can open the Task Manager, right-click on the service's process name, and select the Debug option from the context menu. This spawns the debugger and attaches it to your service. You can now set breakpoints, debug the service code, and even test how your service responds to control notifications. Here are a few problems with connecting the debugger to the service:
If you really want to use this approach to debug your service's initialization code, you can do it easily enough by simply adding a call to the DebugBreak function inside your (w)main or (w)WinMain function. However, this technique works only if your service runs under the LocalSystem account. If you run your service under a different user account, your debugger will not work properly because the system won't allow it to interact with the interactive window station and desktop.
Here is another technique you can use to debug a service: Windows offers the ability to invoke a debugger whenever a process starts. To have the system do this, you must first create a subkey under the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ CurrentVersion\Image File Execution Options |
Under this key, create a subkey that is the name of your service's executable (without the path). In the executable name subkey, add a string value whose name is Debugger, and set this value equal to the full pathname of your debugger (for example, "C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\msdev.exe").
Once you have all this set up, you can go to the Services snap-in and start the service. The SCM will launch the debugger instead of the service executable. At this point, open your source code file, set breakpoints, and then let the service go. Note that you will have just 30 seconds to do this before the SCM forcibly terminates the debugger (since the service will not have called StartServiceCtrlDispatcher).
If all of these limitations are bothering you, and you want to be able to debug the service in its most natural environment without having to interact with the desktop or worry about which user account the service is logged on to, you can use a kernel debugger.