如何从.Net Core 2.1 / 2.2制作Windows服务 [英] How to make a Windows Service from .Net Core 2.1/2.2

查看:103
本文介绍了如何从.Net Core 2.1 / 2.2制作Windows服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我需要将.Net Core 2.1或2.2控制台应用程序转换为Windows服务。

Recently I had a need to convert a .Net Core 2.1 or 2.2 console application into a Windows Service.

由于我不需要移植此端口进程到Linux,我可以省去我在Stackoverflow上看到的涉及.Net Framework,.Net Standard和.Net Core任意组合的多平台解决方案。

As I didn't have a requirement to port this process to Linux, I could dispense with the multiple platform solutions that I had seen on Stackoverflow that dealt with any combination of .Net Framework, .Net Standard and .Net Core.

进行了一些挖掘和提供了很多帮助,使我有了一些行之有效的方法:

A bit of digging and much help I had something that worked:

推荐答案

在本文中,我将介绍设置的必要步骤将.Net Core 2.1或2.2进程作为Windows服务。



由于我对Linux没有要求,因此我可以寻找针对Windows的解决方案。

有点挖掘,发现了史蒂夫·戈登(Steve Gordon)的一些帖子(谢谢!),特别是在他展示Microsoft.Extensions.Hosting软件包和Windows托管的地方(单击此处(用于发帖),此处(用于他的github示例)。



以下是所需步骤:

In this post I will describe the steps required to set up a .Net Core 2.1 or 2.2 process as a Windows Service.

As I have no requirement for Linux, I could look for a solution that was Windows-specific.
A bit of digging turned up some posts from Steve Gordon (thanks!), in particular where he presents the Microsoft.Extensions.Hosting package and Windows hosting ( click here for post and here for his github sample ).

Here are the steps required:


  • 首先创建.Net核心控制台应用程序。

  • 将语言版本设置为至少7.1,以支持Main方法的异步任务。  (从项目设置-> Build-> Advanced-> Language Settings中访问语言版本。

  • 添加Microsoft.Extensions.Hosting和System.ServiceProcess.ServiceController程序包。

  • 编辑项目.csproj文件,并将其包含在PropertyGroup中:< RuntimeIdentifier> win7-x64< / RuntimeIdentifier>

  • 确保您已经在PropertyGroup < OutputType> Exe< / OutputType>

  • First create a .Net Core console application.
  • Set the language version to at least 7.1 to support async Task for the Main method.  (Access the language version from the project settings->Build->Advanced->Language Settings.
  • Add the Microsoft.Extensions.Hosting and the System.ServiceProcess.ServiceController packages.
  • Edit the project .csproj file and include in the PropertyGroup: <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
  • Insure you have in the PropertyGroup  <OutputType>Exe</OutputType>

现在转到Program.cs并复制以下内容:

Now go to Program.cs and copy the following:

using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AdvancedHost
{
    internal class Program
    {
        private static async Task Main(string[] args)
        {
            var isService = !(Debugger.IsAttached || args.Contains("--console"));

            var builder = new HostBuilder()
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<LoggingService>();
                });

            if (isService)
            {
                await builder.RunAsServiceAsync();
            }
            else
            {
                await builder.RunConsoleAsync();
            }
        }
    }
}

此代码将支持交互式调试和生产执行,并运行示例类LoggingService。





这是服务本身的骨架示例:

This code will support interactive debugging and production execution, and runs the example class LoggingService.


Here is a skeleton example of the service itself:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace AdvancedHost
{
    public class LoggingService : IHostedService, IDisposable
    {

        public Task StartAsync(CancellationToken cancellationToken)
        {
            // Startup code

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {           
            // Stop timers, services
            return Task.CompletedTask;
        }

        public void Dispose()
        {
            // dispose of non-managed resources
        }
    }
}

完成项目所需的最后两个文件:

The final two files necessary to complete the project:

ServiceBaseLifetime.cs:

ServiceBaseLifetime.cs:

using Microsoft.Extensions.Hosting;
using System;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;

namespace AdvancedHost
{

    public class ServiceBaseLifetime : ServiceBase, IHostLifetime
    {
        private readonly TaskCompletionSource<object> _delayStart = new TaskCompletionSource<object>();

        public ServiceBaseLifetime(IApplicationLifetime applicationLifetime)
        {
            ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));
        }

        private IApplicationLifetime ApplicationLifetime { get; }

        public Task WaitForStartAsync(CancellationToken cancellationToken)
        {
            cancellationToken.Register(() => _delayStart.TrySetCanceled());
            ApplicationLifetime.ApplicationStopping.Register(Stop);

            new Thread(Run).Start(); // Otherwise this would block and prevent IHost.StartAsync from finishing.
            return _delayStart.Task;
        }

        private void Run()
        {
            try
            {
                Run(this); // This blocks until the service is stopped.
                _delayStart.TrySetException(new InvalidOperationException("Stopped without starting"));
            }
            catch (Exception ex)
            {
                _delayStart.TrySetException(ex);
            }
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            Stop();
            return Task.CompletedTask;
        }

        // Called by base.Run when the service is ready to start.
        protected override void OnStart(string[] args)
        {
            _delayStart.TrySetResult(null);
            base.OnStart(args);
        }

        // Called by base.Stop. This may be called multiple times by service Stop, ApplicationStopping, and StopAsync.
        // That's OK because StopApplication uses a CancellationTokenSource and prevents any recursion.
        protected override void OnStop()
        {
            ApplicationLifetime.StopApplication();
            base.OnStop();
        }
    }
}

ServiceBaseLifetimeHostExtensions.cs:

ServiceBaseLifetimeHostExtensions.cs:

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AdvancedHost
{

    public static class ServiceBaseLifetimeHostExtensions
    {
        public static IHostBuilder UseServiceBaseLifetime(this IHostBuilder hostBuilder)
        {
            return hostBuilder.ConfigureServices((hostContext, services) => services.AddSingleton<IHostLifetime, ServiceBaseLifetime>());
        }

        public static Task RunAsServiceAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default)
        {
            return hostBuilder.UseServiceBaseLifetime().Build().RunAsync(cancellationToken);
        }
    }
}

要安装,请运行或删除我使用'sc'实用程序的服务:

In order to install, run or delete the service I use the 'sc' utility:

sc create AdvancedHost binPath="C:\temp\AdvancedHost\AdvancedHost.exe"

其中 AdvancedHost 是服务名称, binPath 的值是已编译的可执行文件。

where AdvancedHost is the service name and the value for binPath is the compiled executable.

一旦创建了服务,就开始:

Once the service is created, to start:

sc start AdvancedHost

要停止:

sc stop AdvancedHost

,最后删除(一次停止):

and finally to delete (once stopped):

sc delete AdvancedHost

sc中包含许多其他功能;只需在命令行上单独输入 sc即可。

There are many more features contained in sc; just type 'sc' alone on the command line.

sc的结果可以在Windows服务控制台中看到。

The results of sc can be seen in the services Windows control panel.

这篇关于如何从.Net Core 2.1 / 2.2制作Windows服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆