65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Topshelf 轻松创建 Windows 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.24/5 (11投票s)

2020年3月3日

CPOL

5分钟阅读

viewsIcon

16670

.NET Core 中创建 Windows 服务的简短教程 - 包含计划任务/实体框架核心/托管 WebApi 的示例

引言

这些示例的核心库是 Topshelf。它提供了一种非常简单的方式来入门 winservice。本文包含 winservice 的示例,这些 winservice 应该执行计划任务或运行 RestApi。

所有示例都使用依赖注入,如果您不熟悉它,这里有一些关于依赖注入和 Autofac 框架的进一步阅读材料。

入门

  • 所有示例均基于 .NET Core 3.1

示例 1 - 基本 winservice

所需的 NuGet 包

Topshelf

  • 执行 EXE 将在控制台中运行服务
  • 可以通过 cmd.exe (以管理员身份运行) 安装 Windowsservice - Service.exe install
  • 卸载使用 Service.exe uninstall

Bootstrap.cs

此类用于注册依赖注入的类型。在此示例中,必须注册包含服务逻辑的 BasicService

示例 2 - Scheduledservice

所需的 NuGet 包

  • Topshelf
  • Topshelf.Autofac
  • Quartz
  • Autofac.Extras.Quartz
  • Microsoft.Extensions.Configuration.Json

Topshelf

  • 执行 EXE 将在控制台中运行服务
  • 可以通过 cmd.exe (以管理员身份运行) 安装 Windowsservice - Service.exe install
  • 卸载使用 Service.exe uninstall

Bootstrap.cs

此类用于注册依赖注入的类型。

  • 注册 Servicecontrollers
  • 注册 IConfiguration - 提供读取 appsettings.json
  • 注册设置 - 便于访问配置的助手类
  • 注册 QuartzModule
  • 注册控制器

Quartz

日志记录

如果作业未执行,请开启 Quartz 的日志记录。QuartzConsoleLogProvider.cs 实现了一个记录到控制台的日志记录器。

注册日志提供程序

LogProvider.SetCurrentLogProvider(new QuartzConsoleLogProvider());
作业

Job 是您的服务应该运行的任务。这些必须实现 IJob 接口。如果此作业需要其他数据,您可以使用 JobDataMap。(参见 «QuartzController.cs» 和 MyJob.cs)

触发器

Quarzt 提供了一些在特定时间执行作业的触发器。示例包含在 QuartzController.cs

  • 执行一次作业。
  • 按间隔执行作业。
  • 从队列中删除作业。

触发器文档

示例 3 - ScheduledEFCoreWinservice

所需的 NuGet 包

  • Topshelf
  • Topshelf.Autofac
  • Quartz
  • Autofac.Extras.Quartz
  • Microsoft.Extensions.Configuration.Json
  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools

Topshelf

  • 执行 EXE 将在控制台中运行服务
  • 可以通过 cmd.exe (以管理员身份运行) 安装 Windowsservice - Service.exe install
  • 卸载使用 Service.exe uninstall

Bootstrap.cs

此类用于注册依赖注入的类型。

  • 注册 Servicecontrollers
  • 注册 IConfiguration - 提供读取 appsettings.json
  • 注册设置 - Helperclass 便于访问配置
  • 注册 QuartzModule
  • 注册 Controller
  • 注册数据库上下文

EF Core 与依赖注入

数据库

示例数据库是免费的 Ip2Location 数据库 的导入。有关下载和导入 MS-SQL 的说明,请查看以下链接:IP2Location™ LITE IP-COUNTRY 数据库

Bootstrap

InstancePerLifetimeScope - 上下文将为每个作业创建,并在作业完成后将其处理。

builder.RegisterType<ip2locationContext>().InstancePerLifetimeScope();
builder.RegisterType<ip2locationWriteContext>().InstancePerLifetimeScope();
背景

由于构造函数 ip2locationContext(IConfiguration configuration),配置将自动注入。配置用于读取连接字符串。

public partial class ip2locationContext : DbContext
{
    protected readonly IConfiguration _configuration;

    public ip2locationContext(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_configuration.GetConnectionString("CTX"));
        }
    }
}
ip2locationContextFactory

如果您想要 EF-Core 迁移,您应该实现此类。否则,EF-Core 工具将找不到您的连接字符串。

Quartz

日志记录

如果作业未执行,请开启 Quartz 的日志记录。QuartzConsoleLogProvider.cs 实现了一个记录到控制台的日志记录器。

注册日志提供程序

LogProvider.SetCurrentLogProvider(new QuartzConsoleLogProvider());
作业

Job 是您的服务应该运行的任务。这些必须实现 IJob 接口。如果此作业需要其他数据,您可以使用 JobDataMap。(参见 «QuartzController.cs» 和 MyJob.cs)

触发器

Quarzt 提供了一些在特定时间执行作业的触发器。示例包含在 QuartzController.cs

  • 执行一次作业。
  • 按间隔执行作业。
  • 从队列中删除作业。

触发器文档

示例 4 - WebapiWinservice

所需的 NuGet 包

  • Topshelf
  • Topshelf.Autofac
  • Microsoft.Extensions.Configuration.Json
  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.AspNetCore
  • Microsoft.AspNetCore.Core
  • Microsoft.AspNetCore.Server.Kestrel.Core
  • Microsoft.Extensions.Hosting
  • Microsoft.Extensions.Logging.Configuration

Topshelf

  • 执行 EXE 将在控制台中运行服务
  • 可以通过 cmd.exe (以管理员身份运行) 安装 Windowsservice - Service.exe install
  • 卸载使用 Service.exe uninstall

项目设置

  1. 控制台应用程序 (.NET Core 3.1)
    • 用于 windowsservice
    • 打开项目文件 - 将项目 Sdk 编辑为:<Project Sdk="Microsoft.NET.Sdk.Web">
  2. 类库 (.NET STandard 2.0)
    • 如果需要 C# 应用程序的响应对象,请创建类库。或者,您也可以只使用从 JSON 解析的动态对象。

appsettings.json

  • 必须配置 KestrelLogging 部分。
  • "AllowedHosts": "192.168.130.16;test.example.com" - 通过此配置,您可以定义 WebApi 可以从哪些主机访问。

发布提示

  • 应配置 AllowedHosts
  • 如果 API 只在内部可用,请配置 Windows 防火墙

调试

!!! 不要使用 IIS-Express 执行 !!!

debugging

Bootstrap.cs

此类用于注册依赖注入的类型。

BuildContainer
  • 注册 servicecontroller
RegisterGlobalTypes

这些类型必须注册两次。一次用于 ASP.NET webhost,一次用于您的 service controller。

  • 注册 IConfiguration - 提供读取 appsettings.json
  • 注册设置 - Helperclass 便于访问配置

WebApi

初始化

构建 webhost

定义 kestrel 服务器的设置

_webHost = Host.CreateDefaultBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
        webBuilder.ConfigureKestrel(serverOptions =>
        {
            serverOptions.Limits.MaxConcurrentConnections = 100;
            serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
            serverOptions.Limits.MaxRequestBodySize = 30 * 1024 * 1024;
            serverOptions.Limits.MinRequestBodyDataRate =
                new MinDataRate(bytesPerSecond: 100,
                    gracePeriod: TimeSpan.FromSeconds(10));
            serverOptions.Limits.MinResponseDataRate =
                new MinDataRate(bytesPerSecond: 100,
                    gracePeriod: TimeSpan.FromSeconds(10));
            serverOptions.Limits.KeepAliveTimeout =
                TimeSpan.FromMinutes(2);
            serverOptions.Limits.RequestHeadersTimeout =
                TimeSpan.FromMinutes(1);
        });
    })
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .Build();
Startup.cs

ConfigureContainer

注册 Autofac 的类型

public void ConfigureContainer(ContainerBuilder builder)
{
    Bootstrap.RegisterGlobalTypes(builder);
    builder.RegisterType<Ip2LocationController>();
    // is used for determining the client ip
    builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
    // context per request
    builder.RegisterType<ip2locationContext>().InstancePerLifetimeScope();
}

配置

如果 HostHttpsRedirect 设置为 «1»,服务将自动重定向到 HTTPS。

Settings settings = app.ApplicationServices.GetAutofacRoot().Resolve<Settings>();
if (settings.GetAppSetting("HostHttpsRedirect") == "1")
{
    app.UseHttpsRedirection();
}
开始/停止
// Start
_webHost.StartAsync().ConfigureAwait(false).GetAwaiter().GetResult();
// Stop 
_webHost.StopAsync().ConfigureAwait(false).GetAwaiter().GetResult();
ApiController
  1. 继承自 ControllerBase
  2. 设置 Route & ApiController 属性
  3. 实现 HttpGet / HttpPost 方法
示例 C# 客户端

项目 «WebapiWinserviceClientExample»。

EF Core 与依赖注入

数据库

示例数据库是免费的 Ip2Location 数据库 的导入。有关下载和导入 MS-SQL 的说明,请查看以下链接:IP2Location™ LITE IP-COUNTRY 数据库

Bootstrap

InstancePerLifetimeScope - 上下文将为每个作业创建,并在作业完成后将其处理。

builder.RegisterType<ip2locationContext>().InstancePerLifetimeScope();
builder.RegisterType<ip2locationWriteContext>().InstancePerLifetimeScope();
背景

由于构造函数 ip2locationContext(IConfiguration configuration),配置将自动注入。配置用于读取连接字符串。

public partial class ip2locationContext : DbContext
{
    protected readonly IConfiguration _configuration;

    public ip2locationContext(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_configuration.GetConnectionString("CTX"));
        }
    }
}
ip2locationContextFactory

如果您想要 EF-Core 迁移,您应该实现此类。否则,EF-Core 工具将找不到您的连接字符串。

历史

  • 2020 年 3 月 2 日:初始版本
© . All rights reserved.