Bug: Service not starting when using Topshelf
cufeo opened this issue · 2 comments
cufeo commented
Hey! Thank you for your awesome library! I have this issue when using Serilog with Topshelf, the console application works as expected but when trying to start it as a service. It gives this error:
Error 1053: The service did not respond to the start or control request in a timely fashion
To Reproduce
Environment
- .NET 5.0
- Topshelf 4.3.0
- Serilog 2.10.0
- Serilog.Sinks.Console 4.0.0
- Serilog.Sinks.GoogleCloudLogging 3.5.0
- Topshelf.Serilog 4.3.0
Dummy Console App
using Serilog;
using Serilog.Sinks.GoogleCloudLogging;
using System;
using System.Timers;
using Topshelf;
namespace App
{
public class TownCrier
{
readonly Timer _timer;
public TownCrier()
{
_timer = new Timer(2000) { AutoReset = true };
_timer.Elapsed += (sender, eventArgs) => Log.Information("All is well!");
}
public void Start() { _timer.Start(); }
public void Stop() { _timer.Stop(); }
}
public class Program
{
public static void Main()
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "gckey.json");
var config = new GoogleCloudLoggingSinkOptions { ProjectId = "dummy-project", UseJsonOutput = true, ServiceName = "demolog", LogName = "demolog" };
// Logging
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.GoogleCloudLogging(config)
.CreateLogger();
var rc = HostFactory.Run(x => //1
{
x.UseSerilog();
x.Service<TownCrier>(s => //2
{
s.ConstructUsing(name => new TownCrier()); //3
s.WhenStarted(tc => tc.Start()); //4
s.WhenStopped(tc => tc.Stop()); //5
});
x.RunAsLocalSystem(); //6
x.SetDescription("Sample Topshelf Host"); //7
x.SetDisplayName("Stuff"); //8
x.SetServiceName("Stuff"); //9
}); //10
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11
Environment.ExitCode = exitCode;
}
}
}
Build and run the service
- In a new
.bat
file add:
cd /d C:\PathToProject\Bin\Debug\net5.0
ProjectName.exe install
ProjectName.exe start
pause
- Then run it as an admin
cufeo commented
Solved by adding:
public static void Main()
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Directory.SetCurrentDirectory(path);
...
}
manigandham commented
hey @cufeo
Glad you got it figured out. I"m assuming the issue was with the Google Cloud JSON credentials file? Instead of setting the current directory, you can set the full path to the JSON as the environment variable (instead of just the name). More info about how the authentication works in the official Google Cloud .NET repo here:
https://github.com/googleapis/google-cloud-dotnet#authentication