Reputation: 5003
I have created a .net core console application using TopShelf. But I got an error when running the application using docker (alpine-linux).
Configuration Result:
[Success] Name MyApp
[Success] DisplayName MyApp
[Success] Description My Application
[Success] ServiceName MyApp
Topshelf v4.1.0.177, .NET Framework v4.0.30319.42000
Topshelf.Runtime.Windows.WindowsHostEnvironment Error: 0 : Unable to get parent process (ignored), System.DllNotFoundException: Unable to load shared library 'kernel32.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: Error loading shared library libkernel32.dll: No such file or directory
at Topshelf.Runtime.Windows.Kernel32.CreateToolhelp32Snapshot(UInt32 dwFlags, UInt32 th32ProcessID)
at Topshelf.Runtime.Windows.WindowsHostEnvironment.GetParent(Process child)
Topshelf.HostFactory Error: 0 : The service terminated abnormally, System.PlatformNotSupportedException: ServiceController enables manipulating and accessing Windows services and it is not applicable for other operating systems.
at System.ServiceProcess.ServiceController.GetServices()
at Topshelf.Runtime.Windows.WindowsHostEnvironment.IsServiceListed(String serviceName)
at Topshelf.Hosts.ConsoleRunHost.Run()
at Topshelf.HostFactory.Run(Action`1 configureCallback)
How to solve this issue? I need to run my console application as a windows service
Upvotes: 5
Views: 3876
Reputation: 14577
The Topshelf documentation is pretty specific:
To work with Topshelf you will need to be running on a Windows operating system. The developers of Topshelf regulary test on Windows 7 and Windows Server 2008RC2. Though it should still work on Windows Server 2003, as long as .Net 3.5 sp1 is installed.
The good news is that writing Linux daemons is easier than Windows Services - all they have to be is basically a console application where you control the main loop.
If I got your problem statement correctly, you want to be able to run one service both in Windows and in Docker. In this case it seems the easiest way will be to examine your OS environment on start up with something like System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform()
and either defer your main work to Topshelf or run it Linux-style. For the example below I installed Microsoft.Extensions.Hosting
package and opted for implementing an IHostedService (which Topshelf can conveniently reuse)
public class YourHostedService : IHostedService, IDisposable
{
private int executionCount = 0;
private Timer _timer;
public YourHostedService()
{
}
public Task StartAsync(CancellationToken stoppingToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
executionCount++;// this gets called every 5 seconds
}
public Task StopAsync(CancellationToken stoppingToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose() => _timer?.Dispose();
}
public class Program
{
public static async Task Main(string[] args)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var rc = HostFactory.Run(x =>
{
var token = CancellationToken.None;
x.Service<YourHostedService>(s =>
{
s.ConstructUsing(name => new YourHostedService());
s.WhenStarted(tc => tc.StartAsync(token));
s.WhenStopped(tc => tc.StopAsync(token));
});
x.RunAsLocalSystem();
x.SetDescription("TopShelf Host");
x.SetDisplayName("YourHostedService");
x.SetServiceName("YourHostedService");
});
}
else
{
await Host.CreateDefaultBuilder(args)
.ConfigureServices(builder =>
{
builder.AddHostedService<YourHostedService>();
})
.RunConsoleAsync();
}
}
}
More inspiration can be drawn from here.
UPD So it seems your particular case can also be solved by running arbitrary (well, in this case your) program as Windows service. In this case you've got some options that don't involve programming but rather config writing:
.exe
Upvotes: 5
Reputation: 481
Topshelf is not a good choice for .NET Core because .Net Core has powerful facilities for build Windows Service. Furthermore, TopShelf is only supporting Windows. See Examples:
https://medium.com/@tocalai/create-windows-service-using-net-core-console-application-dc2f278bbe42
https://codeburst.io/create-a-windows-service-app-in-net-core-3-0-5ecb29fb5ad0
Upvotes: 0
Reputation: 5584
So your requirement is to run a dotnet core (which version?) application as a windows service.
TopShelf might not be the right tool for this, as it supports .NET Framework 4.0 or Mono, not dotnet core.
Since you want to run a windows service, it does not make any sense to publish your app as a Linux Docker image! Use sc create
and sc start
to register and start your published executable instead.
Upvotes: 1