Easier way to debug a Windows service

后端 未结 28 1923
春和景丽
春和景丽 2020-11-22 15:36

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

28条回答
  •  無奈伤痛
    2020-11-22 16:23

    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:
    FrameworkException

    Afterwards, escpecially in Windows 7 UAC might prompt you to enter admin credentials. Enter them and proceed with Yes:

    UACPrompt

    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: VSDebuggerPrompt

    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). VSDebuggerBreakpoint

    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.

提交回复
热议问题