Easier way to debug a Windows service

后端 未结 28 1570
春和景丽
春和景丽 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:15

    You can also start the service through the command prompt (sc.exe).

    Personally, I'd run the code as a stand-alone program in the debugging phase, and when most bugs are ironed out, change to running as service.

    0 讨论(0)
  • 2020-11-22 16:20

    What I used to do was to have a command line switch which would start the program either as a service or as a regular application. Then, in my IDE I would set the switch so that I could step through my code.

    With some languages you can actually detect if it's running in an IDE, and perform this switch automatically.

    What language are you using?

    0 讨论(0)
  • 2020-11-22 16:21

    To debug Windows Services I combine GFlags and a .reg file created by regedit.

    1. Run GFlags, specifying the exe-name and vsjitdebugger
    2. Run regedit and go to the location where GFlags sets his options
    3. Choose "Export Key" from the file-menu
    4. Save that file somewhere with the .reg extension
    5. Anytime you want to debug the service: doubleclick on the .reg file
    6. If you want to stop debugging, doubleclick on the second .reg file

    Or save the following snippets and replace servicename.exe with the desired executable name.


    debugon.reg:

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
    "GlobalFlag"="0x00000000"
    "Debugger"="vsjitdebugger.exe"

    debugoff.reg:

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
    "GlobalFlag"="0x00000000"
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-11-22 16:23

    This YouTube video by Fabio Scopel explains how to debug a Windows service quite nicely... the actual method of doing it starts at 4:45 in the video...

    Here is the code explained in the video... in your Program.cs file, add the stuff for the Debug section...

    namespace YourNamespace
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main()
            {
    #if DEBUG
                Service1 myService = new Service1();
                myService.OnDebug();
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    #else
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]
                {
                    new Service1()
                };
                ServiceBase.Run(ServicesToRun);
    #endif
    
            }
        }
    }
    

    In your Service1.cs file, add the OnDebug() method...

        public Service1()
        {
            InitializeComponent();
        }
    
        public void OnDebug()
        {
            OnStart(null);
        }
    
        protected override void OnStart(string[] args)
        {
            // your code to do something
        }
    
        protected override void OnStop()
        {
        }
    

    How it works

    Basically you have to create a public void OnDebug() that calls the OnStart(string[] args) as it's protected and not accessible outside. The void Main() program is added with #if preprocessor with #DEBUG.

    Visual Studio defines DEBUG if project is compiled in Debug mode.This will allow the debug section(below) to execute when the condition is true

    Service1 myService = new Service1();
    myService.OnDebug();
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    

    And it will run just like a console application, once things go OK you can change the mode Release and the regular else section will trigger the logic

    0 讨论(0)
  • 2020-11-22 16:23

    Just put your debugger lunch anywhere and attach Visualstudio on startup

    #if DEBUG
        Debugger.Launch();
    #endif
    

    Also you need to start VS as Administatrator and you need to allow, that a process can automatically be debugged by a diffrent user (as explained here):

    reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
    
    0 讨论(0)
提交回复
热议问题