Is there an easier way to step through the code than to start the service through the Windows Service Control Manager and then attaching the debugger to the thread? It\'s ki
Sometimes it is important to analyze what's going on during the start up of the service. Attaching to the process does not help here, because you are not quick enough to attach the debugger while the service is starting up.
The short answer is, I am using the following 4 lines of code to do this:
#if DEBUG
base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
Debugger.Launch(); // launch and attach debugger
#endif
These are inserted into the OnStart
method of the service as follows:
protected override void OnStart(string[] args)
{
#if DEBUG
base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
Debugger.Launch(); // launch and attach debugger
#endif
MyInitOnstart(); // my individual initialization code for the service
// allow the base class to perform any work it needs to do
base.OnStart(args);
}
For those who haven't done it before, I have included detailed hints below, because you can easily get stuck. The following hints refer to Windows 7x64 and Visual Studio 2010 Team Edition, but should be valid for other environments, too.
Important: Deploy the service in "manual" mode (using either the InstallUtil
utility from the VS command prompt or run a service installer project you have prepared). Open Visual Studio before you start the service and load the solution containing the service's source code - set up additional breakpoints as you require them in Visual Studio - then start the service via the Service Control Panel.
Because of the Debugger.Launch
code, this will cause a dialog "An unhandled Microsoft .NET Framework exception occured in Servicename.exe." to appear. Click Yes, debug Servicename.exe as shown in the screenshot:
Afterwards, escpecially in Windows 7 UAC might prompt you to enter admin credentials. Enter them and proceed with Yes:
After that, the well known Visual Studio Just-In-Time Debugger window appears. It asks you if you want to debug using the delected debugger. Before you click Yes, select that you don't want to open a new instance (2nd option) - a new instance would not be helpful here, because the source code wouldn't be displayed. So you select the Visual Studio instance you've opened earlier instead:
After you have clicked Yes, after a while Visual Studio will show the yellow arrow right in the line where the Debugger.Launch
statement is and you are able to debug your code (method MyInitOnStart
, which contains your initialization).
Pressing F5 continues execution immediately, until the next breakpoint you have prepared is reached.
Hint: To keep the service running, select Debug -> Detach all. This allows you to run a client communicating with the service after it started up correctly and you're finished debugging the startup code. If you press Shift+F5 (stop debugging), this will terminate the service. Instead of doing this, you should use the Service Control Panel to stop it.
Note that
If you build a Release, then the debug code is automatically removed and the service runs normally.
I am using Debugger.Launch()
, which starts and attaches a debugger. I have tested Debugger.Break()
as well, which did not work, because there is no debugger attached on start up of the service yet (causing the "Error 1067: The process terminated unexpectedly.").
RequestAdditionalTime
sets a longer timeout for the startup of the service (it is not delaying the code itself, but will immediately continue with the Debugger.Launch
statement). Otherwise the default timeout for starting the service is too short and starting the service fails if you don't call base.Onstart(args)
quickly enough from the debugger. Practically, a timeout of 10 minutes avoids that you see the message "the service did not respond..." immediately after the debugger is started.
Once you get used to it, this method is very easy because it just requires you to add 4 lines to an existing service code, allowing you quickly to gain control and debug.