使用WinSW将jar创建成Windows服务;使用Microsoft.Extensions.Hosting.WindowsServices将.net转换成Windows服务

发布时间 2023-12-20 14:07:20作者: sun-sailing

【背景】我们有几个历史产品,需要部署在Windows系统上,产品有jar包,也有.net工程,为了优美的启动服务,思考了两种处理方式。

  第一种是电脑开机启动,将启动命令设置为快捷键,并将快捷键拷贝到C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup目录下,该方式有个缺点,由于jar包启动方式都是使用javaw启动,当一个windows中有多个jar包已这种方式开机启动,在进程中无法区分是哪个服务,导致更包时需要全部重启。

  第二种是将后台软件部署成windows服务,本文以真实的案例指导实现方式,参考:使用WinSW将nacos安装为windows服务;参考:使用.NET Core创建Windows服务详细步骤

 

 

【实践1】使用WinSW将jar创建成Windows服务

关键要素:

序号

模块

文件名

描述

1

work-service

work-install.bat

安装服务

2

work-uninstall.bat

删除服务

3

work-service.exe

Winsw服务(将winsw服务修改便于识别)

4

work-service.xml

服务配置

1、下载WinSW:https://github.com/winsw/winsw/releases,下载版本:WinSW v2.12.0->WinSW-x64.exe,17.4MB

2、准备配置,将以下四个文件与jar放在同一个目录下

(1)WinSW-x64.exe修改为work-service.exe,即以系统服务命名

(2)新建服务配置文件:work-service.xml

<service>
    <id>work-service</id>
    <name>work-service</name>
    <description>work服务</description>
    <executable>java</executable>
    <arguments>-server -Xms1024m -Xmx1024m -XX:PermSize=256m -XX:SurvivorRatio=2 -XX:+UseParallelGC -jar .\work.jar --spring.config.location=application.yml</arguments>
    <logpath>logs</logpath>
    <startmode>Automatic</startmode>
</service>

(3)新建安装服务文件:work-install.bat

  work-service.exe install
  work-service.exe start

 (4)新建卸载服务文件:work-uninstall.bat

  work-service.exe stop
  work-service.exe uninstall

3、执行操作

(1)鼠标双击work-install.bat,创建服务,并启动,可以在系统->服务中查询到服务名称为work-service的服务。

(2)鼠标双击work-uninstall.bat,停止并删除服务,系统->服务中work-service被删除了。

【实践2】使用Microsoft.Extensions.Hosting.WindowsServices将.net转换成Windows服务

该方式需要引入包Microsoft.Extensions.Hosting.WindowsServices,同时在Program.cs中添加UseWindowsService方法调用,

本文以work-service服务为例子:

(1)源码修改如下

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using log4net;

namespace WorkServer
{
    static class Program
    {
        public static readonly ILog Log = LogManager.GetLogger(typeof(Program));

        static async Task Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args);
            //判断当前系统是否为windows
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                host.UseWindowsService();
            }
            return host.ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
        }
    }

    public class Worker : BackgroundService
    {
        public static readonly ILog Log = LogManager.GetLogger(typeof(Worker));
        private readonly ILogger<Worker> _logger;


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

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            try
            {
                //TODO 业务代码
                while (!stoppingToken.IsCancellationRequested)
                {
                    //TODO 业务代码
                    Log.Info("Worker running at: {DateTimeOffset.Now}");
                    await Task.Delay(1000, stoppingToken);
                }
            }
            catch (Exception e)
            {
                Log.Error("main:ExecuteAsync failed.", e);
            }
            
        }
    }
}

(2)新建安装服务文件:work-install.bat

@sc create work-service binPath= "D:\work\WorkServer.exe"
@sc start work-service
@sc config work-service start= AUTO

 (3)新建卸载服务文件:work-uninstall.bat

@sc stop work-service