アルパカのメモ

Windows サービスを作る

概要

前提条件:

  • .NET Core 3.1
  • Visual Studio 2019 で開発

プロジェクトの作成

「Worker Service」のテンプレートを使い、プロジェクトを作成する。

プロジェクトを作成するときに下記のような画面が出るが、そのまま「作成」をクリック。

プロジェクトが作成されると、下記のようなファイルたちが作られる。

Windows サービスに必要な設定をする

このままだと、コンソールアプリとしては起動するものの、Windows サービスとしては起動しない。 このプロジェクトをそのままビルドして Windows サービスとして登録しても、起動しようとしたときに「エラー 1053: そのサービスは指定時間内に開始要求または制御要求に応答しませんでした」というエラーになる。

NuGet パッケージの追加

下記パッケージをプロジェクトへ追加する。

Microsoft.Extensions.Hosting.WindowsService

このとき、プロジェクトが最初からインストールしている Microsoft.Extensions.Hosting のバージョンが古いと WindowsService の追加に失敗することがある。 そのときは、Microsoft.Extensions.Hosting のバージョンを最新版へ更新する。

Program.cs の編集

Program.cs を開き、HostBuilder のところに UseWindowsService メソッドを追加する。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WorkerService1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                })
                .UseWindowsService();
    }
}

サービスの処理を実装

サービスのビジネスロジックは、Worker.cs へ実装する。 ExecuteAsync メソッド内にループ処理が書かれているので、この中に処理を書く。 このループはサービスが中断されるまで続くので、同じ処理を定期的に繰り返すことになる。

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

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

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

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                // ここに処理を書く
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);

                // 1秒待機してループ
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

サービスの発行と登録

まず、プロジェクトを「発行」して、リリース版のexeファイルを作成する。その後、出来上がったexeファイルをサービスとして登録する。 次に、コマンドプロンプトを「管理者として実行」し、下記コマンドを実行する。

sc create "Service Name" binpath="path_to_exe\service.exe"

参考

Create Windows Services. .Net Core 3.0 | by LAI TOCA | Medium