.NET 8에서 Windows용 서비스 만들기Create a service for Windows in .NET 8

페이지 업데이트 :
페이지 생성 날짜 :

운영 환경

비주얼 스튜디오
  • 비주얼 스튜디오 2022
.그물
  • .그물 8
윈도우
  • 윈도우 11

필수 구성 요소

비주얼 스튜디오
  • 비주얼 스튜디오 2022
.그물
  • .그물 8
윈도우
  • 윈도우 10
  • 윈도우 11
윈도우 서버
  • Windows 2012 이상

전제 조건

  • Visual Studio가 이미 설치되어 있습니다.

처음에

NET에서 Windows 서비스를 만들려고 하면 .NET Framework 템플릿만 있습니다. .NET(Core)에서도 만들 수 있으며 템플릿 이름은 "Worker Service"입니다.

이 기사에서는 이를 사용하여 Windows 서비스를 생성, 등록 및 실행하는 방법을 설명합니다. 처리 내용이 최소화되어 있으므로 Windows 서비스로 실행되고 있음을 확인할 수 있으면 함수를 생성하십시오.

프로젝트 만들기

Visual Studio를 시작합니다. 새 프로젝트 만들기를 선택합니다.

サービス 위의 검색 필드에 입력한 다음, 목록에서 Worker Service를 선택합니다. "Windows 서비스"는 .NET 버전이 없는 .NET Framework 버전입니다.

프로젝트 이름과 위치는 임의로 지정할 수 있습니다. 등록하는 서비스에는 영향을 미치지 않습니다.

「. 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 이 메서드는 취소 플래그가 지정될 때까지 while stoppingToken으로 계속 반복됩니다. 서비스가 실행되는 동안 처리할 항목을 while 추가합니다. 다만, 이동하고자 하는 프로세스만 작성하면 서비스가 최대 용량으로 운영되기 때문에 Task.Delay 메소드를 이용하여 일정 시간 대기하면서 이동하는 것이 기본입니다. 기본적으로 1초(1000ms)로 설정되어 있으므로 언제든지 다시 작성하십시오.

디버그

Visual Studio에서 디버그할 수 있습니다. 실제로 서비스에 등록되지 않으므로 안심하십시오.

실행하면 콘솔이 나타납니다.

프로세스가 올바르면 파일이 생성되었음을 알 수 있습니다.

디버깅을 중지하려면 콘솔을 닫습니다.

로그를 확인하면 서비스 시작 프로세스는 통과했지만 종료 프로세스는 통과하지 않은 것을 확인할 수 있습니다. 종료를 보려면 실제로 Windows 서비스에 등록하여 확인해야 합니다.

출판하다

Windows 서비스에 등록하려면 프로그램을 게시해야 합니다. 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Publish(게시)를 선택합니다.

폴더를 선택합니다.

폴더 위치는 기본적으로 좋습니다.

게시 설정이 생성되므로 "모든 설정 표시"를 선택합니다.

다음과 같이 설정합니다.

매개 변수 이름 값 설명
구성 릴리스(기본값)
Target Framework net8.0(기본값)
배포 모드 Framework Dependency 서비스 등록 환경에 대해 별도입니다. NEt 8 런타임을 설치하는 경우 이 설정은 괜찮습니다.
타겟 런타임 윈-x64 OS가 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 <サービス名>