Консольное приложение ядра.net с использованием верхней полки
Я создал консольное приложение ядра.net с использованием верхней полки. Но я получил ошибку при запуске приложения с помощью 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
0 ответов
Документация Topshelf довольно конкретна:
Для работы с Topshelf вам потребуется операционная система Windows. Разработчики Topshelf регулярно тестируют на Windows 7 и Windows Server 2008RC2. Хотя он должен работать в Windows Server 2003, если установлен.Net 3.5 sp1.
Хорошая новость заключается в том, что писать демонов 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();
}
}
}
Больше вдохновения можно сделать здесь.
UPD Так что, похоже, ваш конкретный случай также можно решить, запустив произвольную (в данном случае вашу) программу как службу Windows. В этом случае у вас есть несколько вариантов, которые не связаны с программированием, а скорее с написанием конфигурации:
- В собственном инструменте SrvAny компании Microsoft, которая была частью NT Resource Kit: вы в основном установить его в качестве фиктивной службы и редактировать параметр реестра, чтобы указать на
.exe
- Третий SrvStart инструмента стороны: это один относительно легко подобрать так, и конфигурация подобна выше
Итак, ваше требование - запустить приложение ядра dotnet (какая версия?) В качестве службы Windows.
TopShelf может быть не подходящим инструментом для этого, поскольку он поддерживает.NET Framework 4.0 или Mono, а не ядро dotnet.
Поскольку вы хотите запустить службу Windows, нет смысла публиковать свое приложение как образ Linux Docker! Использоватьsc create
а также sc start
чтобы вместо этого зарегистрироваться и запустить опубликованный исполняемый файл.
Topshelf - не лучший выбор для.NET Core, потому что.Net Core имеет мощные возможности для сборки Windows Service. Кроме того, TopShelf поддерживает только Windows. См. Примеры:
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