使用TopShelf的.NET Core控制台应用程序

5
我使用TopShelf创建了一个.net core控制台应用程序。但是在使用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服务运行


如果您想将控制台应用程序运行为Windows服务,此链接可能会对您有所帮助。 - RPrashant
1
错误的操作系统,这只能在Windows上运行。 重复内容在此。Linux的替代方案在此 - Hans Passant
3个回答

5

Topshelf文档非常明确:

要使用Topshelf,您需要运行在Windows操作系统上。Topshelf的开发人员经常在Windows 7和Windows Server 2008RC2上进行测试。虽然只要安装了.Net 3.5 sp1,它也应该可以在Windows Server 2003上运行。

好消息是,编写Linux守护进程比Windows服务更容易 - 它们只需要基本上是一个控制主循环的控制台应用程序。

如果我正确理解了您的问题陈述,您希望能够在Windows和Docker中同时运行一个服务。在这种情况下,似乎最简单的方法是使用类似于System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform()这样的内容检查您的操作系统环境,并将主要工作推迟到Topshelf或像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();
        }
    }
}

更多灵感可以从这里获得。

更新 看起来你的特殊情况也可以通过将任意(在这种情况下是你的)程序运行为Windows服务来解决。 在这种情况下,你有一些不需要编程而是需要编写配置文件的选项:

  1. Microsoft自己的工具SrvAny,它已经成为NT Resource Kit的一部分了:你只需安装它作为虚拟服务,并编辑注册表设置以指向你的 .exe 文件
  2. 一个第三方工具SrvStart:这个相对容易上手,配置与上述类似

1
您的要求是将一个 .NET Core 应用程序作为 Windows 服务运行。可能不适合使用 TopShelf,因为它只支持 .NET Framework 4.0 或 Mono,而不是 dotnet core。由于您想要运行 Windows 服务,将应用程序发布为 Linux Docker 镜像没有任何意义!请使用 sc createsc start 注册和启动已发布的可执行文件。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接