Problems Converting Console App to Topshelf Service

182 views
Skip to first unread message

Ron Mittelman

unread,
Jul 21, 2020, 11:24:43 PM7/21/20
to topshelf-discuss

I am developing a data access layer using NancyFX in console app.  So far, it's working fine.

I am using VS 2019 and this is a .Net Core 3.0 application.

Trying to convert to a Windows Service using TopShelf.  Original code in Main:

static void Main(string[] args) 
{
    Logger.LogInfo("NancyDataService starting...");
    var uri = new Uri(ConfigurationManager.AppSettings["uri"]);      var hostConfig = new HostConfiguration();
    
hostConfig.UrlReservations.CreateAutomatically = true;
    hostConfig.RewriteLocalhost = false;
    using (var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig))
    {
        Try
        {
            nancyHost
.Start();
            Console.WriteLine($"Nancy now listening on {uri}.\n\nPress any key to exit");
            Logger.LogInfo($"Nancy now listening on {uri}...");
        }
        catch (Exception ex)
        {
            Logger.LogError(ex.Message);
            Console.WriteLine("Error " + ex.Message + "\n\nPress any key to exit");
        }
        Console.ReadKey();
        Logger.LogInfo("NancyDataService stopped...");
    }
}  

When I open browser and go to http://localhost:8080/whatever, the Nancy endpoint properly services the request, depending on path. 

When incorporating Topshelf, here is new Main code:

static void Main(string[] args)
{
    
Logger.LogInfo("NancyDataService starting...");
    var rc = HostFactory.Run(x =>
    {
        x.Service<DataService>();
        x.EnableServiceRecovery(r => r.RestartService( TimeSpan.FromSeconds(10)));
        x.SetServiceName("NancyDataService");
        x.RunAsLocalService();
        x.StartAutomatically();
    });
    var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());
    Environment.ExitCode = exitCode;
}

DataService Code:

class DataService : ServiceControl
{
    public bool Start(HostControl hostControl)
    {
        // start Nancy here
        var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
        var hostConfig = new HostConfiguration();
        hostConfig.UrlReservations.CreateAutomatically = true;
        hostConfig.RewriteLocalhost = false;
        using var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig);
        try
        {
            nancyHost.Start();
            Console.WriteLine($"Nancy now listening on {uri}.\n\nPress any key to exit");
            Logger.LogInfo($"Nancy now listening on {uri}...");
            return true;
        }
        catch (Exception ex)
        {
            Logger.LogError(ex.Message);
            Console.WriteLine("Error " + ex.Message + "\n\nPress any key to exit");
            return false;
        }
    }
    public bool Stop(HostControl hostControl)
    {
        Logger.LogInfo("NancyDataService stopped.");
        return true;
    }
}

So now when I run the application, it seems to run ok and start Nancy listening on that port.  Also, logging and console show program has started and is listening on that port.  But when I type the url in browser and hit Enter, I get "The site can't be reached. localhost refused to connect."

I'm sure I'm missing something, but can't figure out what.

Any ideas?  Thanks...


Ron Mittelman

unread,
Jul 23, 2020, 2:42:12 PM7/23/20
to topshelf-discuss
Forgot to include some pieces in DataService class.

1:  Removed : ServiceControl from class declaration and changed Start and Stop methods to void.
2:  In Start method, added this to end of Try block:

    // spin thread here
    _semaphoreToRequestStop = new SemaphoreSlim(0);
    _thread = new Thread(DoWork);
    _thread.Start();

3:  Added DoWork method to keep things going:
private void DoWork(object obj)
{
    while (true)
    {
        Console.WriteLine("doing work..");
        if (_semaphoreToRequestStop.Wait(500))
        {
            Console.WriteLine("Stopped");
            break;
        }
    }
}

Ron Mittelman

unread,
Jul 24, 2020, 2:00:27 PM7/24/20
to topshelf-discuss
Figured out the problem.  It had more to do with threading and scoping of my objects.  Now it works fine...
Reply all
Reply to author
Forward
0 new messages