Hangfire Windows Service using Topshelf returns timeout error

##Hangfire Windows Service using Topshelf returns timeout error
I have seen a few people on the forum mention using Topshelf to create a Windows service for Hangfire so I am hoping someone can help me.

I would like to convert my console app for running Hangfire jobs into a service by using Topshelf but so far nothing I have tried has worked. I have verified that running as a console app the program is working fine and running the jobs as expected. However when I install the same console app as a service and then try to start it it always times out. I hope I am just missing some simple thing that will make it work.

My console app has NuGet package references to Hangfire.Core, Hangfire.SqlServer, Topshelf, and the web application that has the job code. The web app defines the job and registers it in the database and hosts the dashboard. I have verified that the web app and console app both point to same shared database and the run as user account can connect. Again, as long as I just run the console app directly everything works fine.

##Code I am using

namespace ErpWeb.Job.Service
{
    using Hangfire;

    using Topshelf;

    public class ErpWebBackgroundJobService : ServiceControl
    {
        private BackgroundJobServer server;

        public bool Start(HostControl hostControl)
        {
            GlobalConfiguration.Configuration.UseSqlServerStorage("DqAppsConnString");

            this.server = new BackgroundJobServer();
            
            return true;
        }

        public bool Stop(HostControl hostControl)
        {
            this.server.Dispose();

            return true;
        }
    }

    class Program
    {

        static int Main(string[] args)
        {
            HostFactory.Run(x =>
            {
                x.Service<ErpWebBackgroundJobService>();
                x.SetServiceName("ErpWeb.Job.Service");
                x.SetDescription("ErpWeb.Job.Service");
                x.StartAutomatically();
                x.RunAs(@"serviceAccountName", "********");
                x.EnableServiceRecovery(r => r.RestartService(1));
            });

            return 0;
        }
    }
}

##Debugging

If I run the console app in Visual Studio with Debug -> Start I get this result in the console:

Configuration Result:
[Success] Name ErpWeb.Job.Service
[Success] ServiceName ErpWeb.Job.Service
Topshelf v4.0.0.0, .NET Framework v4.0.30319.42000
The ErpWeb.Job.Service service is now running, press Control+C to exit.
Running job
Job done

Installing the service


I try installing as a service with ErpWeb.Job.Service.exe install and I get this result in the console:

>ErpWeb.Job.Service.exe install
Configuration Result:
[Success] Name ErpWeb.Job.Service
[Success] ServiceName ErpWeb.Job.Service
Topshelf v4.0.0.0, .NET Framework v4.0.30319.42000

Running a transacted installation.

Beginning the Install phase of the installation.
Installing ErpWeb.Job.Service service
Installing service ErpWeb.Job.Service...
Service ErpWeb.Job.Service has been successfully installed.

The Install phase completed successfully, and the Commit phase is beginning.

The Commit phase completed successfully.

The transacted install has completed.

##Starting the service

I try starting the service with ErpWeb.Job.Service start and I get this result in the console:

>ErpWeb.Job.Service.exe start
Configuration Result:
[Success] Name ErpWeb.Job.Service
[Success] ServiceName ErpWeb.Job.Service
Topshelf v4.0.0.0, .NET Framework v4.0.30319.42000
Topshelf.Hosts.StartHost Error: 0 : The service failed to start., System.ServiceProcess.TimeoutException: Time out has e
xpired and the operation has not been completed.
   at System.ServiceProcess.ServiceController.WaitForStatus(ServiceControllerStatus desiredStatus, TimeSpan timeout)
   at Topshelf.Runtime.Windows.WindowsHostEnvironment.StartService(String serviceName, TimeSpan startTimeOut)
   at Topshelf.Hosts.StartHost.Run()

It took about 30 seconds for the timeout to happen so I added more time with x.SetStartTimeout(TimeSpan.FromSeconds(60)) and then it times out after 60 seconds. I also tried 120. During these times it never ran the job which is a recurring job to run every 60 seconds.

I got to the bottom of this finally. It had nothing to do with Hangfire or Topshelf. The run as user account was missing some permissions and caused the GlobalConfiguration.Configuration.UseSqlServerStorage(“DqAppsConnString”); to fail.

He was trying to check if the Hangfire schema was present but lacked the SQL server access for that.

Since I did not have any error handling to log the details it just crashed with the Timeout error.

To debug a case like this Topshelf was very helpful once I paid attention to what I was doing. I was debugging in Visual Studio as myself and then deploying the server as the service account. I ran a command prompt as the service account and then started up the executable and the error details were displayed.