Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't start worker service as windows service

So. I created a worker service and want to run it as windows service. It works locally. I installed it to windows server via powershell new-service command. When I start it via Services, it attempts to start, waits for 30 seconds (with loading bar progressing) and fails. In event viewer I see generic errors:

  1. A timeout was reached (30000 milliseconds) while waiting for the MyService service to connect.
  2. The MyService service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion.

Now, the weird thing is, I added some logging to service logic, and it actually does needed stuff, windows just fails to start it, i.e. service does not respond to start, but works (for 30 seconds, after that server kills it because it gave no response for start). How do I fix it? My Program.cs:

    public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            File.AppendAllText("templogs.txt", ex.Message + "\r\n");
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .ConfigureServices((hostContext, services) =>
            {
                IConfiguration configuration = hostContext.Configuration;
                services.AddHostedService<Worker>();
                services.AddScoped<IActionHandler, ActionHandler>();
                services.AddScoped<IHttpHandler, HttpHandler>();
                services.AddDbContext<DbContext>(options =>
                {
                    options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
                });
                File.AppendAllText("templogs.txt", "context registered\r\n");

            });
}

Worker service:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly List<string> _inactiveStatuses;
    private readonly IServiceProvider _services;
    private readonly string _connectionString;


    public Worker(ILogger<Worker> logger, IConfiguration config, IServiceProvider services)
    {
        try
        {
            _logger = logger;
            _inactiveStatuses = config.GetSection("InactiveStatuses").GetChildren().Select(a => a.Value).ToList();
            _services = services;
            _connectionString = config.GetConnectionString("DefaultConnection");
        }
        catch (Exception ex)
        {
            File.AppendAllText("templogs.txt", ex.Message + "\r\n");
        }
    }
    public override async Task StartAsync(CancellationToken cancellationToken)
    {
        await base.StartAsync(cancellationToken);
    }

    public override async Task StopAsync(CancellationToken cancellationToken)
    {
        await base.StopAsync(cancellationToken);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            using (var scope = _services.CreateScope())
            {
                File.AppendAllText("templogs.txt", "scope created\r\n");

                var actionHandler =
               scope.ServiceProvider
                   .GetRequiredService<IActionHandler>();
                var dbContext = scope.ServiceProvider.GetRequiredService<DbContext>();
                var activeStatuses = dbContext.Statuses.Where(a => !_inactiveStatuses.Contains(a.Name)).ToDictionary(a => a.Id, a => a.Name);
                List<Guid> activeStatusGuids = activeStatuses.Keys.ToList();
                while (!stoppingToken.IsCancellationRequested)
                {
                    File.AppendAllText("templogs.txt", "while strated\r\n");
                    //some logic
                    File.AppendAllText("templogs.txt", "first cycle\r\n");

                    await Task.Delay(1000, stoppingToken);
                }
            }
        }
        catch (Exception ex)
        {
            File.AppendAllText("templogs.txt", ex.Message + "\r\n");
        }
    }
}
like image 863
Jamil Avatar asked Sep 18 '25 16:09

Jamil


1 Answers

We just fought the same issue!

The problem is that Service Control Manager requires an extra callback to switch the service to "running".

This is handled by the Microsoft.Extensions.Hosting.WindowsServices (separate NuGet), and appending CreateHostBuilder(...).UseWindowsService();

like image 200
chura Avatar answered Sep 21 '25 06:09

chura