Debugging Tools for Windows |
This topic lists all the preparatory steps that may be required prior to debugging a service application. Which steps are required in your scenario depends on which attach option you have chosen and which debugging configuration you have chosen. For a list of these choices, see Choosing the Best Method.
Each of the preparatory steps described in this topic specifies the conditions under which it is required. These steps can be done in any order.
If you plan to debug the service application from the beginning of its execution, including its initialization code, this preparatory step is required.
Locate or create the following registry key, where ProgramName is the name of the service application's executable file:
ProgramName should include the file name extension, but not the path. For example, ProgramName might be Myservice.exe or Thisservice.dll.
Under this registry key, create a string data value entitled Debugger. The value of this string should be set to the full path and file name of a debugger to be attached to the service application.
Do not choose this option if you are running Windows Vista or a later version of Windows.
If your debugging session begins before Windows is fully loaded, you may not be able to access symbols from a remote share; in such a case, you must use local symbols. ServerTransport must specify a transport protocol that is implemented by the Windows kernel without interfacing with a user-mode service, such as TCP or NPIPE. For the syntax of ServerTransport, see Activating a Debugging Server.
If you plan to use this method and your user-mode symbols will be accessed from a symbol server, you should combine this method with remote debugging. In this case, specify NTSD with the
For details, see Controlling the User-Mode Debugger from the Kernel Debugger.
After this registry edit is complete, the debugger is launched whenever a service with this name is started or restarted.
If you want the service application to break into the debugger when it crashes or encounters an exception, this preparatory step is required. This step is also required if you want the service application to break into the debugger by calling the DebugBreak function.
Note: If you have enabled debugging of the initialization code (the step described in the subsection Enabling the Debugging of the Initialization Code), you should skip this step. When initialization code debugging is enabled, the debugger attaches to the service application when it starts, which causes all crashes, exceptions, and calls to DebugBreak to be routed to the debugger without additional preparations being needed.
This preparatory step involves registering the chosen debugger as the postmortem debugger. This is done by using the
Do not choose this option if you are running Windows Vista or a later version of Windows.
In the pipe specification, the %x token is replaced with the process ID of the process that launches the debugger. This guarantees that if more than one process launches a postmortem debugger, each has a unique pipe name. If your debugging session begins before Windows is fully loaded, you may not be able to access symbols from a remote share; in such a case, you must use local symbols. ServerTransport must specify a transport protocol that is implemented by the Windows kernel without interfacing with a user-mode service, such as TCP or NPIPE. For the syntax of ServerTransport, see Activating a Debugging Server.
If you choose this method and intend to access user-mode symbols from a symbol server, you should combine this method with remote debugging. In this case, specify NTSD with the
For details, see Controlling the User-Mode Debugger from the Kernel Debugger.
When you issue one of these commands, the postmortem debugger is registered. This debugger will be launched whenever any user-mode program, including a service application, encounters an exception or runs a DebugBreak function.
If you plan to launch the debugger automatically (either when the service starts or when it encounters an exception), this preparatory step is required.
Locate the following registry key:
Under this key, locate or create a DWORD data value called ServicesPipeTimeout. Set this entry to the amount of time in milliseconds that you want the service to wait before timing out. For example, a value of 60,000 is one minute, while a value of 86,400,000 is 24 hours. When this registry value is not set, the default timeout is about thirty seconds.
The significance of this value is that a clock starts to run when each service is launched, and when the timeout value is reached, any debugger attached to the service is terminated. Therefore, the value you choose should be longer than the total amount of time that elapses between the launching of the service and the completion of your debugging session.
This setting applies to every service that is started or restarted after the registry edit is complete. If some service crashes or hangs and this setting is still in effect, the problem is not detected by Windows. Therefore, you should use this setting only while you are debugging, and return the registry key to its original value after your debugging is complete.
Sometimes, multiple services are combined in a single Service Host (Svchost) process. If you want to debug such a service, you must first isolate it into a separate Svchost process.
There are three methods by which you can isolate a service. Microsoft recommends the Moving the Service to its Own Group method, as follows. The alternative methods (Changing the Service Type and Duplicating the SvcHost Binary) can be used on a temporary basis for debugging, but because they alter the way the service runs, they are not as reliable as the first method.
Preferred Method: Moving the Service to its Own GroupThis displays the current configuation values for the service. The value of interest is BINARY_PATH_NAME, which specifies the command line used to launch the service control program. In this scenario, because your service is not yet isolated, this command line includes a directory path, Svchost.exe, and some SvcHost parameters, including the
Remember this path and the group name; they are used in steps 5 and 6.
Create a new REG_MULTI_SZ value with a unique name (for example, TempGrp).
Now the SvcHost key contains a value with the new name and also has a subordinate key with this same name.
For example, the old key might be named this:
and it might contain values such as CoInitializeSecurityParam, AuthenticationCapabilities, and other values. You would go to the newly created key:
and create values in it that are identical in name, type, and data to those in the old key.
If the old key does not exist, you do not need to create a new key.
In this command, ServiceName is the name of the service, and RevisedPath is the new value you are supplying for BINARY_PATH_NAME. For RevisedPath, use the exact same path as the one displayed in step 1, including all the options shown on that line, making only one change: replace the parameter following the
For example, your command might look like this:
You may want to use the sc qc command again to review the change you have made.
These settings will take effect the next time the service is started. To clear the effects of the old service, we recommend that you restart Windows rather than just restarting the service.
After you have completed your debugging, if you want to return this service to the shared service host, use the sc config command again to return the binary path to its original value, and delete the new registry keys and values you created..
Alternative Method: Changing the Service TypeThe space after the equal sign is required.
net start ServiceName
This alternative is not the recommended method because it can alter the behavior of the service. If you do use this method, use the following command to revert to the normal behavior after you have completed your debugging:
This command displays the current configuation values for the service. The value of interest is BINARY_PATH_NAME, which specifies the command line used to launch the service control program. In this scenario, because your service is not yet isolated, this command line will include a directory path, Svchost.exe, and probably some SvcHost parameters. For example, it may look something like this:
In this command, ServiceName is the name of the service, and RevisedPath is the new value you are supplying for BINARY_PATH_NAME. For RevisedPath, use the exact same path as the one displayed in step 2, including all the options shown on that line, making only one change: replace Svchost.exe with Svchost2.exe. Enclose RevisedPath in quotation marks. The space after the equal sign is required.
For example, your command might look like this:
You can use the sc qc command again to review the change you have made.
net start ServiceName
This alternative is not the recommended method because it can alter the behavior of the service. If you do use this method, use the sc config command to change the path back to its original value after you have completed your debugging.