2

I would like that Topshelf stops my service when I debug it in a console.

My code:

public class Program
{
    private static ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    public static void Main(string[] args)
    {
        HostFactory.Run(Configure);
    }

    /// <summary>
    /// Configures the service host.
    /// </summary>
    /// <param name="cfg">The HostConfigurator</param>
    private static void Configure(HostConfigurator cfg)
    {
        try
        {
            cfg.Service<ServiceHost>(s =>
            {
                s.ConstructUsing(name => new ServiceHost());
                s.WhenStarted(host => host.StartService());
                s.WhenStopped(host => host.StopService());
            });

            cfg.RunAsLocalSystem();
            cfg.StartManually();
            cfg.SetDisplayName(DisplayName);
            cfg.SetServiceName(ServiceName);
            cfg.UseLog4Net();
        }
        catch (Exception ex)
        {
            _log.Fatal("Exception on Startup", ex);
            throw;
        }
    }
}

But when I press CTRL+C it hangs in Microsoft.VisualStudio.HostingProcess.HostProc.WaitForThreadExit.

When I press CTRL+C I would like that host => host.StopService() is called immediately.

Is that possible?

jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
leozilla
  • 1,296
  • 2
  • 19
  • 29
  • Have you tried turning off VS Hosting in your project's properties? – Jay Feb 05 '14 at 09:25
  • good idea! i tried it but now it hangs in > mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext) + 0x2b bytes :( – leozilla Feb 05 '14 at 09:45
  • Ctrl+C is a pretty big hammer, pretty hard for code to dodge it. You'll need to post a better stack trace to give us a guess. Beware of a common deadlock in the Console class for .NET 4.5 RTM, do make sure you have Windows Update enabled to get the service release that fixes it. – Hans Passant Feb 05 '14 at 12:03
  • The solution is to enabled unmanaged debugging and turn off the Control+C exception handler as discussed in this question: http://stackoverflow.com/questions/3949106/vs2010-express-debugger-trapping-ctrlc-in-console-app – Chris Patterson Feb 14 '14 at 15:05

5 Answers5

2

It should be possible to intercept the CTRL+C by adding an event handler to the Console.CancelKeyPress event:

Console.CancelKeyPress += (s, e) => host.StopService();
Luaan
  • 62,244
  • 7
  • 97
  • 116
  • i already tried this, it always blocks on "Microsoft.VisualStudio.HostingProcess.HostProc.WaitForThreadExit". – leozilla Feb 05 '14 at 09:02
  • Seems that this is a bug in the .net framework: http://connect.microsoft.com/VisualStudio/feedback/details/524889/debugging-c-console-application-that-handles-console-cancelkeypress-is-broken-in-net-4-0 – leozilla Feb 05 '14 at 09:06
  • @leozilla Yeah, but it seems to only be there when you're debugging. Perhaps you could use a different key combination to stop the service when debugging? For example, I'm waiting for "q" press, then I do a clean shutdown. – Luaan Feb 05 '14 at 09:30
  • Topshelf's ConsoleRunHost already handles the Ctrl+C keypress. – Chris Patterson Feb 14 '14 at 15:02
1

The most likely culprit is that your service's StartService method doesn't return control to Topshelf. What does your StartService do? It should only initialize any resources and start up your event loop/thread. Can you run service install start and get it to start up? If the service times out while starting up, it would also reinforce the idea that your start isn't returning.

Travis
  • 10,444
  • 2
  • 28
  • 48
0

its a known bug with .NET 4.0, there is a workaround but its nasty

https://github.com/Topshelf/Topshelf/issues/10

leozilla
  • 1,296
  • 2
  • 19
  • 29
0

In VS2010, you need to:

  1. Go to your project property, then navigate to Debug pane, check 'Enable unmanaged code debugging'.
  2. Toolbar Debug-> Exceptions -> then Uncheck the C++ Exceptions and the Win32 Exceptions.
Rokey Ge
  • 681
  • 8
  • 18
0

In your ServiceHost class implement IDisposeable, add a Dispose method, and dispose all your threaded objects.

John H
  • 502
  • 6
  • 9