AspNet Core 部署为Windows服务


目录
  • 基于 Web 应用的服务
    • 发布
    • 脚本
      • 安装为服务并运行
      • 停止并卸载服务
    • 安装为 WindowsServer
    • 删除安装失败的服务
    • 重新发布安装
    • 卸载服务
  • 服务仅执行后台任务
    • 脚本
  • 依赖部署 VS 独立部署

官方文档:
https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-3.0&tabs=visual-studio
官方示例:
https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/host-and-deploy/windows-service

部署为windowsServer,首先要看网站是基于什么类型的!
对于使用 Razor Pages 或 MVC 框架的基于 Web 应用的服务,请在项目文件中指定 Web SDK:


如果服务仅执行后台任务(例如 托管服务),请在项目文件中指定辅助角色 SDK:


不同的网站类型,选择不同的的依赖包;

    
    
    
    

当然可以这两种的网站类型是可以同时存在,官方示例,就是这样子的,

项目工程文件:



  
    net6.0
    enable
    enable
    
    true
  

  
    
    
    
    
  

                                                                             |

Program.cs

// 托管服务
builder.Services.AddHostedService();

// 基于 Web 应用的服务
builder.Host.UseWindowsService();

其中,托管服务 ServiceA 的定义如下:

public class ServiceA : BackgroundService
    {
        public ServiceA(ILoggerFactory loggerFactory)
        {
            Logger = loggerFactory.CreateLogger();
        }

        public ILogger Logger { get; }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Logger.LogInformation("ServiceA is starting.");

            stoppingToken.Register(() => Logger.LogInformation("ServiceA is stopping."));

            while (!stoppingToken.IsCancellationRequested)
            {
                Logger.LogInformation("ServiceA is doing background work.");

                await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
            }

            Logger.LogInformation("ServiceA has stopped.");
        }
    }

基于 Web 应用的服务

创建 AspNet Core 项目,项目名称为:WebWinServer1
添加包 Microsoft.Extensions.Hosting.WindowsServices


  ...
  
    ...
    
  



接着修改 Program.cs

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService()//指定项目可以部署为Windows服务
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup()
                        .UseUrls("http://*:8787"); //使用的端口号
                });

发布

右键工程文件,在菜单中选择【发布】,设置发布配置

注意,这里的
部署模式:选择【框架依赖】,目标框架选择 netcoreapp3.1

但是我的电脑没有 .netcore3.1的运行时,之所以这样设置,只是为了测试和模拟真实的生成环境可能遇到的情况
多个网站版本不同,需要安装各个版本的运行时,这有不太可能,除非使用Docker部署。

其中,发布文件地址是:

E:\webpulish\web-winserver

然后点击发布

脚本

参见:https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/host-and-deploy/windows-service/samples/scripts

安装为服务并运行

创建文件install.bat

set serviceName=AspNetCore-WinServer
set serviceFilePath=%cd%\WebWinServer1.exe
set serviceDescription=AspNetCoreweb程序部署为WindowsServer
sc create %serviceName% binPath=%serviceFilePath%
sc config %serviceName% start=auto  
sc description %serviceName% %serviceDescription%
sc start %serviceName%
pause

停止并卸载服务

创建文件uninstall.bat

set serviceName=AspNetCore-WinServer
sc stop  %serviceName%
sc delete %serviceName%
pause

安装为 WindowsServer

把上面创建的安装脚本 install.bat 和卸载脚本 uninstall.bat 复制到发布文件跟目录,示例中的目录是:

E:\webpulish\web-winserver

使用管理员身份打开CMD,执行安装脚本 install.bat

注意:一定要是管理员身份打开,否则报错:

[SC] OpenService 失败 5:拒绝访问
>E:
>E:\>cd E:\webpulish\web-winserver
>E:\webpulish\web-winserver>install.bat
....
E:\webpulish\web-winserver>sc.exe start AspNetCore-WinServer
[SC] StartService 失败 2:

服务启动失败,这是因为,我的电脑用的是 .Net 6,现在发布的目标框架是.netcoreapp3.1
本机没有.netcore3.1的运行时。所以启动失败!

删除安装失败的服务

执行以下命令,删除服务

sc delelte AspNetCore-WinServer

虽然删除WindowsServer成功,但是服务列表中还是存在,要彻底删除,
打开系统注册表,删掉服务的注册表信息,通常路径在:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services 找到你的Service服务的名字,然后把整个文件夹删掉
这时,服务列表中还是存在服务:AspNetCore-WinServer,重启电脑即可。

重新发布安装

上节说到我的电脑用的是.Net 6,现在发布的目标框架是.netcoreapp3.1 ,这种情况跟实际的生成环境一样,
生成环境有多个网站,第一个网站是 .netcore3.1, 第二个网站是基于.net5, 第三个网站是.net6,
这时不可能同时安装3个版本的 .net运行时,所以发布的时候,发布配置如下:

部署模式:选择【独立】,目标框架选择 netcoreapp3.1,如下图所示:

点击发布。
复制 安装脚本 install.bat到发布目录:E:\webpulish\web-winserver
然后打开CMD【管理员身份】,切换到发布目录 ,执行安装脚本 install.bat

E:\webpulish\web-winserver>install.bat

输入结果

E:\webpulish\web-winserver>set serviceName=AspNetCore-WinServer
E:\webpulish\web-winserver>set serviceFilePath=E:\webpulish\web-winserver\WebWinServer1.exe
E:\webpulish\web-winserver>set serviceDescription=AspNetCoreweb程序部署为WindowsServer
E:\webpulish\web-winserver>sc config AspNetCore-WinServer start=auto
[SC] ChangeServiceConfig 成功
E:\webpulish\web-winserver>sc description AspNetCore-WinServer AspNetCoreweb程序部署为WindowsServer
[SC] ChangeServiceConfig2 成功
E:\webpulish\web-winserver>sc start AspNetCore-WinServer
SERVICE_NAME: AspNetCore-WinServer
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 11148
        FLAGS              :
E:\webpulish\web-winserver>pause

安装成功,启动也成功了。

访问站点:http://localhost:8787/

卸载服务

用管理员身份打开CMD,执行如下卸载脚本 uninstall.bat

>E:
>E:\>cd E:\webpulish\web-winserver
>E:\webpulish\web-winserver>uninstall.bat

输出结果:

E:\webpulish>set serviceName=AspNetCore-WinServer
E:\webpulish>sc stop  AspNetCore-WinServer
SERVICE_NAME: AspNetCore-WinServer
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

E:\webpulish>sc delete AspNetCore-WinServer
[SC] DeleteService 成功
E:\webpulish>pause
请按任意键继续. . .

删除成功

,此时服务只是被禁用,属于标记删除,如果要彻底删除,使用注册表删除,见上一节的具体操作。

服务仅执行后台任务

创建控制台程序,项目名称为:WorkerWinService,修改项目工程文件为:

 

添加包 Microsoft.AspNetCore.Hosting.WindowsServices

 
  ...
  
     ...
    
  

接着修改 Program.cs

       public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService(); // 添加托管服务
                });

定义后台托管服务:Worker, 继承 BackgroundService
Worker.cs

    public class Worker : BackgroundService
    {
        private readonly ILogger _logger;

        public Worker(ILogger logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }

脚本

安装和卸载脚本同上,只是修改服务名称为 WorkerWinService 即可。

依赖部署 VS 独立部署

参见:https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-3.0&tabs=visual-studio