How to debug the .NET Windows Service OnStart method?

C#.NetDebugging

C# Problem Overview


I have code written in .NET that only fails when installed as a Windows service. The failure doesn't allow the service to even start. I can't figure out how I can step into the OnStart method.

How to: Debug Windows Service Applications gives a tantalizing clue:

>Attaching to the service's process allows you to debug most but not all of the service's code; for example, because the service has already been started, you cannot debug the code in the service's OnStart method this way, or the code in the Main method that is used to load the service. One way to work around this is to create a temporary second service in your service application that exists only to aid in debugging. You can install both services, and then start this "dummy" service to load the service process. Once the temporary service has started the process, you can then use the Debug menu in Visual Studio to attach to the service process.

However, I'm not clear how it is exactly that you are supposed to create the dummy service to load the service process.

C# Solutions


Solution 1 - C#

One thing you could do as a temporary workaround is to launch the debugger as the first line of code in the OnStart

System.Diagnostics.Debugger.Launch()

This will prompt you for the debugger you'd like to use. Simply have the solution already open in Visual Studio and choose that instance from the list.

Solution 2 - C#

I tend to add a method like this:

    [Conditional("DEBUG")]
    private void AttachDebugger()
    {
        Debugger.Break();
    }

it will only get called on Debug builds of you project and it will pause execution and allow you to attach the debugger.

Solution 3 - C#

Once you have a service that is installed using installutil.exe, you can alter the Start Parameters to jump into the debugger if the service is started:

enter image description here

When you manually start the service with the parameter -debugWithVisualStudio (or simply -d), it will automatically detect the correct project, and fire up the interactive debugger in Visual Studio:

enter image description here

To support this functionality, change the service's OnStart() function:

/// <summary>
///     Executed when the service is started.
/// </summary>
/// <param name="args">Command line arguments.</param>
protected override void OnStart(string[] args)
{
	try
	{
		//How to debug when running a Windows Service:
		// 1. Right click on the service name in Windows Service Manager.
		// 2. Select "Properties".
		// 3. In "Start Parameters", enter "-d" (or "-debugWithVisualStudio").
		// 4. Now, when you start the service, it will fire up Visual Studio 2012 and break on the line below.
		// 5. Make sure you have UAC (User Access Control) turned off, and have Administrator privileges.
#if DEBUG
		if (((ICollection<string>)args).Contains("-d")
		    || ((ICollection<string>)args).Contains("-debugWithVisualStudio"))
		{
			Debugger.Launch(); // Launches VS2012 debugger.
		}
#endif
		ShellStart(args);
		base.OnStart(args);
	}
	catch (Exception ex)
	{
        // Log exception here.
	}
}

(optional) If you want to narrow down to the exact line of code where the service is throwing an error, switch on exceptions from the Visual Studio menu DEBUG .. Exceptions. When you continue debugging, it will break on the exact line that is throwing the exception.

enter image description here

Solution 4 - C#

It works just fine!

protected override void OnStart(string[] args)
{
    System.Diagnostics.Debugger.Launch();
}

Solution 5 - C#

The options above did not appear to work on Windows 8.

I have added Thread.Sleep(15000); into my OnStart() method and set a breakpoint on the next line of the code. This give me 15 seconds to attach VS debugger to my process after starting the service and allowed me to debug the OnStart() method nicely.

Solution 6 - C#

You can add a line of code like this:

System.Diagnostics.Debugger.Break()

which will bring up a window prompting you to choose which debugger to use to debug, e.g. allowing you to attach with Visual Studio and step into the code.

see:

http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break.aspx

Solution 7 - C#

It's possible to set up a companion project to the Windows Service that runs as a console app, but accesses the service methods using Reflection. See here for details and an example: http://ryan.kohn.ca/articles/how-to-debug-a-windows-service-in-csharp-using-reflection/.

Solution 8 - C#

Use following Code in Service OnStart Method:

System.Diagnostics.Debugger.Launch();

Choose Visual Studio option from Pop Up message. Remember to run Visual Studio as Administrator.

Note: To use it in only Debug mode, #if DEBUG compiler directive can be used, as follows. This will prevent accidental or Debugging in Release mode on Production server.

#if DEBUG
    System.Diagnostics.Debugger.Launch();
#endif

Solution 9 - C#

As others have pointed out, you have to add a debugger break to the OnStart-Method:

#if DEBUG
    System.Diagnostics.Debugger.Break()
#endif

Also start VisualStudio as Administrator and allow, that a process can automatically be debugged by a different user (as explained [here][1]):

reg add "HKCR\AppID\{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f

(I also explained this here: https://stackoverflow.com/a/35715389/5132456 )

[1]: http://blogs.msdn.com/b/dsvc/archive/2012/12/30/jit-debugging-using-visual-studio-may-fail-when-trying-to-debug-a-session-0-process-on-windows-8.aspx "here"

Solution 10 - C#

I know this is late but this is how we handle debuging Windows services

First create a class which will act as the service.

Add the appropriate methods for starting, stopping, pausing, etc...

Add a windows form to the service project.

In the service code create the service class created above and make the calls needed to start and stop the service in the ServiceBase class

Open the Program.cs and add the following

#if DEBUG
    [STAThread]
#endif
    static void Main()
    {
try
        {
#if DEBUG
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new DebugForm());
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
		{ 
			new YourWindowsService() 
		};
            ServiceBase.Run(ServicesToRun);
#endif
        }
        catch (Exception e)
        {
            logger.Error(DateTime.Now.ToString() + " - " + e.Source + " - " + e.ToString() + "\r\n------------------------------------\r\n");
        }
}

When you run in DEBUG mode the windows form will launch. Just remember to build in Release mode when finished. Of course the conditional compile variable can be anything you like. You could even create seperate projects so the debug form is its own project.

Hope this helps

Solution 11 - C#

You can also try System.Diagnostics.Debugger.Launch() method. It helps in taking the debugger pointer to the specified location and you can then debug you code.

Before this step please install your service.exe using the command line of Visual Studio command prompt - installutil projectservice.exe

Then start your service from the Control Panel -> Administrative Tools -> Computer Management ->Service and Application -> Services -> Your Service Name

Solution 12 - C#

If you add Debugger.Launch() in your OnStart method and it doesn't work, you could have the same issue I had, namely, the exception was occurring in the constructor so the OnStart was never called. (head slap)

(sorry if this should have been a comment on someone else' answer, but i don't have enough cred to make comments)

Solution 13 - C#

Try adding Debugger.Break inside the problematic method. When the service will start an exception will be thrown and widows should offer to debug it using visual studio.

Solution 14 - C#

I usually have a console app that pretends to be the SCM e.g. calls Start, Stop which I can then just F5 into for my main coding/debugging purposes, and use the Debugger.Break for debugging when the service has been installed and started via the SCM.

It means a bit more work to start with, I have a class lib that contains all the service code, with a class that exposes Start and Stop that the Windows Service class and the console app can both call.

Matt

Solution 15 - C#

Before I go in the topic one advise. Always use log specially if you are server side developer. Because there are some certain condition which you might not be able to produce while debugging the code in visual studio.

Coming back to topic, I use Envoirnment.UserInteractive flag this is really handy see my code below

public static void Main(string[] args)
{

    if (System.Environment.UserInteractive)
    {
        string parameter = string.Concat(args);

        switch (parameter)
        {
            case "--install":
                ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                break;
            case "--uninstall":
                ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                break;
            default:
                WindowsService service = new WindowsService();
                service.OnStart(args);
                Console.ReadKey();
                service.OnStop();
                break;
        }
    }
    else
    {
        ServiceBase.Run(new WindowsService());
    }
}

From visual studio you will get UserInteractive flag set so i would run it as console application, In addition to that even you can run product build by double clicking it and attaching debugger with it if you like to test it.

Solution 16 - C#

I have an interesting way of doing this I add another Configuration called DebugNoService

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugNoService|AnyCPU' ">
    <OutputPath>.\</OutputPath>
    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
    <BaseAddress>285212672</BaseAddress>
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
    <ConfigurationOverrideFile>
    </ConfigurationOverrideFile>
    <DefineConstants>DEBUG;TRACE;DEBUGNOSERVICE</DefineConstants>
    <DocumentationFile>
    </DocumentationFile>
    <DebugSymbols>true</DebugSymbols>
    <FileAlignment>4096</FileAlignment>
    <NoStdLib>false</NoStdLib>
    <NoWarn>
    </NoWarn>
    <Optimize>false</Optimize>
    <RegisterForComInterop>false</RegisterForComInterop>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
    <WarningLevel>4</WarningLevel>
    <DebugType>full</DebugType>
    <ErrorReport>prompt</ErrorReport>
    <UseVSHostingProcess>false</UseVSHostingProcess>
  </PropertyGroup>

I use the #if directive. ProjectInstaller.cs

#if !DEBUGNOSERVICE    
   static void Main()
   {
      System.ServiceProcess.ServiceBase[] ServicesToRun;
      .....
   }
#endif

I add a windows form and I also wrap the windows form in

#if DEBUGNOSERVICE
...
static void Main() 
{
    Form     form;

    Application.EnableVisualStyles();
    Application.DoEvents();

    form = new <the name of the form>();

    Application.Run(form);
}
...
#endif

depending on the configuration selected the code either runs as a windows form application that can be easily debugged or as a service.

If seems like a lot of work but it has always worked and makes debugging the code very very easy. You can have all sorts of output added to the form so you can watch it run.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNathanView Question on Stackoverflow
Solution 1 - C#palehorseView Answer on Stackoverflow
Solution 2 - C#HasaniHView Answer on Stackoverflow
Solution 3 - C#ContangoView Answer on Stackoverflow
Solution 4 - C#NoWarView Answer on Stackoverflow
Solution 5 - C#Boris HurinekView Answer on Stackoverflow
Solution 6 - C#Alex BlackView Answer on Stackoverflow
Solution 7 - C#Ryan KohnView Answer on Stackoverflow
Solution 8 - C#ChiragView Answer on Stackoverflow
Solution 9 - C#wotaniiView Answer on Stackoverflow
Solution 10 - C#Coach DavidView Answer on Stackoverflow
Solution 11 - C#Abhishek SrivastavaView Answer on Stackoverflow
Solution 12 - C#and... breakView Answer on Stackoverflow
Solution 13 - C#Dror HelperView Answer on Stackoverflow
Solution 14 - C#MattView Answer on Stackoverflow
Solution 15 - C#MubasharView Answer on Stackoverflow
Solution 16 - C#M pollackView Answer on Stackoverflow