在 .NET 8 中创建适用于 Windows 的服务Create a service for Windows in .NET 8

更新页 :
页面创建日期 :

操作环境

Visual Studio的
  • Visual Studio 2022
。网
  • .NET 8
窗户
  • 窗户11

先决条件

Visual Studio的
  • Visual Studio 2022
。网
  • .NET 8
窗户
  • 窗户10
  • 窗户11
Windows 服务器
  • Windows 2012 或更高版本

前提

  • 已安装 Visual Studio

起先

当我尝试在 Visual Studio .NET 中创建 Windows 服务时,只有 .NET Framework 模板。 它也可以在 .NET (Core) 中创建,模板名为“Worker Service”。

在本文中,我将解释如何使用它来创建、注册和运行 Windows 服务。 处理内容很少,因此,如果您可以确认它作为 Windows 服务运行,请创建函数。

创建项目

启动 Visual Studio。 选择“创建新项目”。

在上面的 サービス 搜索字段中输入,然后从列表中选择“辅助角色服务”。 “Windows 服务”是 .NET Framework 版本,它没有 .NET 版本。

项目名称和位置可以是任意的。 它不会影响您正在注册的服务。

「. 选择 NET 8.0,并保留默认值以创建它。

项目已创建。

添加库

在初始状态下,它只有一个“服务”功能,没有Windows特定的功能。 从 NuGet 添加可供 Windows 服务使用的库。

右键单击“依赖项”,然后选择“管理 NuGet 包”。

选择“浏览”选项卡, Microsoft.Extensions.Hosting.WindowsServices 然后在搜索字段中输入。 它将出现在列表中,因此请安装它。

单击应用。

它已作为包添加。

编辑程序

这一次,我将创建一个服务,该服务定期将文本作为 Mr./Ms. 添加到文本文件中。

Program.cs

添加 Windows 服务的功能,如下所示:

var builder = Host.CreateApplicationBuilder(args);
// ↓ここから追加
builder.Services.AddWindowsService();
// ↑ここまで追加
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

Worker.cs

您可以任意更改类名,但这次我们将保留默认值。

默认情况下,只有一些方法在 ExecuteAsync 执行服务时进行处理,但让我们按如下方式进行更改:

public class Worker : BackgroundService
{
  private readonly ILogger<Worker> _logger;

  /// <summary>ログの出力先フォルダパス。</summary>
  private const string OutputLogFolderPath = @"C:\Temporary\";

  /// <summary>ログの出力先ファイルパス。</summary>
  private const string OutputLogFilePath = @$"{OutputLogFolderPath}Test.log";


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

  /// <summary>
  /// サービスが開始されたときに呼ばれます。
  /// </summary>
  /// <param name="stoppingToken"></param>
  /// <returns></returns>
  public override async Task StartAsync(CancellationToken stoppingToken)
  {
    if (Directory.Exists(OutputLogFolderPath) == false)
    {
      Directory.CreateDirectory(OutputLogFolderPath);
    }
    File.AppendAllText(OutputLogFilePath, $"StartAsync サービスを開始しました。\r\n");

    await base.StartAsync(stoppingToken);
  }

  /// <summary>
  /// サービスが終了したときに呼ばれます。
  /// </summary>
  /// <param name="stoppingToken"></param>
  /// <returns></returns>
  public override async Task StopAsync(CancellationToken stoppingToken)
  {
    File.AppendAllText(OutputLogFilePath, $"StopAsync サービスを終了しました。\r\n");
    File.AppendAllText(OutputLogFilePath, $"------------------------------\r\n");

    await base.StopAsync(stoppingToken);
  }

  /// <summary>
  /// サービスが実行されたときに呼ばれます。
  /// </summary>
  /// <param name="stoppingToken">サービスの非同期キャンセルトークン。</param>
  /// <returns></returns>
  protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  {
    while (!stoppingToken.IsCancellationRequested)
    {
      File.AppendAllText(OutputLogFilePath, $"{DateTime.Now}\r\n");

      if (_logger.IsEnabled(LogLevel.Information))
      {
        _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
      }
      await Task.Delay(1000 * 60, stoppingToken);
    }
  }
}

我们添加了一个新方法和StopAsync一个新StartAsync方法。 顾名思义,这些方法在服务启动和停止时被调用。 该过程的内容只是创建文件夹和编写文本,因此我将省略解释。

ExecuteAsync 该方法继续使用 stoppingToken 循环,直到 while 它被标记为取消。 添加要在服务运行时进行处理的内容 while 。 但是,如果只编写要移动的进程,则服务将满负荷运行,因此 Task.Delay 使用该方法在等待一定时间的同时移动它是基本的。 默认情况下,它设置为 1 秒(1000 毫秒),因此请随时重写。

调试

可以从 Visual Studio 进行调试。 请放心,您实际上不会注册该服务。

当您运行它时,控制台将出现。

如果该过程正确,您可以看到文件已创建。

如果要停止调试,请关闭控制台。

如果检查日志,可以看到服务启动过程已通过,但终止过程尚未通过。 要查看终止,您需要实际注册 Windows 服务以验证它。

问题

为了能够向 Windows 服务注册,您必须发布该程序。 右键单击项目,然后选择“发布”。

选择文件夹。

默认情况下,文件夹位置很好。

将创建发布设置,因此请选择“显示所有设置”。

按如下方式进行设置:

参数名称 值 注
配置 释放(默认)
目标框架 net8.0 (默认)
部署模式 框架依赖性 单独用于服务注册环境。 如果要安装 NEt 8 运行时,则此设置是可以的。
目标运行时 赢-x64 如果操作系统是 32 位环境,请选择 win-x86
目标位置 违约
创建单个文件
ReadyToRun 编译 任意

设置完成后,点击“提交”按钮。

如果左下角显示“发布成功”,则表示发布成功。

可以通过单击“目标位置”来打开输出文件。

课程安排和服务注册

以管理员权限登录到要注册 Windows 服务的环境。

将发布的文件复制到要将其注册为 Windows 服务的环境中。 您可以将其放置在任何文件夹中,但请记住,Windows 服务将始终引用该文件夹中的程序。

此外,如果发布的文件包含扩展名为 .pdb 的文件,请不要在可以被未指定人员看到的环境中复制它,因为它包含开发信息。

文件就位后,将其注册为 Windows 服务。 使用命令进行注册。 右键单击“开始”菜单,然后选择“终端(管理员)”。 Mr./Ms. 在 Windows 11 环境中运行,但在其他环境中,可以使用管理员权限打开命令提示符。

对于终端,PowerShell 可能会先打开,但 PowerShell 可能无法正确设置,因此请打开“命令提示符”。

您可以使用以下命令将其注册到 Windows 服务中:

格式

sc create "<サービス名>" start=auto binpath="<プログラム(.exe)のパス>"

示例输入

sc create "WindowsServiceDotNet8" start=auto binpath="C:\Service\WindowsServiceDotNet8\WindowsServiceDotNet8.exe"

<サービス名> 是显示在 Windows 服务列表中的名称。 您可以设置单独的显示名称,但如果未指定显示名称,则将显示此名称。 它还会影响注册表,因此首选字母数字服务名称。

start=auto 是在 Windows 启动时自动启动服务的设置。 如果要手动启动它,请删除此说明。

binpath 是程序文件的完整路径。

如果执行命令并 [SC] CreateService SUCCESS 显示 ,则表示成功。

您注册的服务应显示在列表中。

启动服务并检查其操作

如果要运行该服务,可以从服务屏幕或使用以下命令启动它。

sc start <サービス名>

stop 命令如下。

sc stop <サービス名>

如果停止该服务,则可以验证关闭进程是否正在运行。

向服务添加说明

已添加服务的描述字段为空,但您可以使用以下命令进行添加。

sc description <サービス名> "<説明文>"

删除服务

如果要删除服务,可以使用以下命令执行此操作。 您必须在命令提示符下具有管理员权限。

sc delete <サービス名>