我使用topshelf创建了.NET Core Console应用程序。但是我在使用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)
如何解决这个问题?我需要将控制台应用程序作为Windows Service
上架文档非常具体:
要使用Topshelf,您需要在Windows操作系统上运行。Windows 7和Windows Server 2008RC2上Topshelf监管测试的开发人员。尽管它仍应在Windows Server 2003上使用,但只要已安装.NET 3.5 SP1。
好消息是,编写Linux Daemons比Windows Services更容易 - 它们基本上是控制主循环的控制台应用程序。
如果我正确地得到了您的问题声明,您希望能够在Windows和Docker中运行一项服务。在这种情况下,似乎最简单的方法是使用System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform()
之类的东西检查您的操作系统环境然后将您的主要工作推迟到上架或运行Linux风格。在下面的示例中,我安装了Microsoft.Extensions.Hosting
软件包,然后选择实现IHostedService(Topshelf可以方便地重复使用(
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();
}
}
}
可以从这里汲取更多灵感。
upd 因此,看来您的特定情况也可以通过任意(在这种情况下,在这种情况下(作为Windows服务来解决。在这种情况下,您有一些不涉及编程的选项,而是配置写作:
- Microsoft自己的工具SRVANY是NT Resource套件的一部分:您基本上将其安装为虚拟服务,并编辑注册表设置,以指向您的
.exe
- 第三方工具srvstart:这也相对容易拾取,配置与上述相似
,因此您的要求是运行dotnet core(哪个版本?(作为Windows服务。
Topshelf可能不是正确的工具,因为它支持.NET Framework 4.0或Mono,而不是Dotnet Core。
由于您想运行Windows服务,因此以Linux Docker Image发布您的应用程序没有任何意义!使用sc create
和sc start
注册并启动您已发布的可执行文件。
topshelf并不是.net核心的好选择,因为.NET Core具有强大的Windows Service设施。此外,Topshelf仅支持窗口。请参阅示例:
https://medium.com/@tocalai/create-windows-service-service-using-net-core-core-console-application-dc2f278bbe42
https://codeburst.io/create-a-windows-service-app-in-net-core-3-0-5ecb29fb5ad0