Creación de un servicio para Windows en .NET 8

Actualización de la página :
Fecha de creación de la página :

Entorno operativo

Estudio visual
  • Visual Studio 2022
.RED
  • .NET 8
Windows
  • Windows 11

Prerrequisitos

Estudio visual
  • Visual Studio 2022
.RED
  • .NET 8
Windows
  • Windows 10
  • Windows 11
Servidor Windows
  • Windows 2012 o posterior

precondición

  • Visual Studio ya está instalado

Al principio

Cuando intento crear un servicio de Windows en Visual Studio .NET, solo hay plantillas de .NET Framework. También se puede crear en .NET (Core) y la plantilla se denomina "Servicio de trabajo".

En este artículo, explicaré cómo usar esto para crear, registrar y ejecutar un servicio de Windows. El contenido de procesamiento es mínimo, por lo que si puede confirmar que se está ejecutando como un servicio de Windows, cree la función.

Crear un proyecto

Inicie Visual Studio. Seleccione Crear un nuevo proyecto.

Ingrese en el campo de サービス búsqueda de arriba y luego seleccione Servicio de trabajador de la lista. "Servicios de Windows" es la versión de .NET Framework, que no tiene una versión de .NET.

El nombre y la ubicación del proyecto pueden ser arbitrarios. No afecta el servicio para el que se está registrando.

「. NET 8.0 y deje los valores predeterminados para crearlo.

El proyecto ha sido creado.

Adición de bibliotecas

En el estado inicial, solo tiene una función de "servicio" y no funciones específicas de Windows. Agregue una biblioteca que pueda usar un servicio de Windows desde NuGet.

Haga clic con el botón secundario en Dependencias y seleccione Administrar paquetes NuGet.

Seleccione la pestaña Examinar e introduzca en el campo de Microsoft.Extensions.Hosting.WindowsServices búsqueda. Aparecerá en la lista, así que instálalo.

Haga clic en Aplicar.

Se agregó como un paquete.

Edición de programas

Esta vez, crearé un servicio que agregue periódicamente texto a un archivo de texto como Sr./Sra.

Program.cs

Agregue la funcionalidad del servicio de Windows de la siguiente manera:

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

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

Worker.cs

Puedes cambiar el nombre de la clase arbitrariamente, pero por esta vez dejaremos el predeterminado.

De forma predeterminada, solo hay métodos que se procesan ExecuteAsync cuando se ejecuta el servicio, pero vamos a cambiarlo de la siguiente manera:

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);
    }
  }
}

Hemos agregado un nuevo método y StopAsync un nuevo StartAsync método. Como su nombre lo indica, se llama a estos métodos cuando se inicia el servicio y cuando se detiene. El contenido del proceso es simplemente crear carpetas y escribir texto, por lo que omitiré la explicación.

ExecuteAsync El método continúa en bucle con stoppingToken hasta while que se marca para su cancelación. Agregue lo que while desea que se procese mientras se ejecuta el servicio. Sin embargo, si escribes solo el proceso que quieres mover, el servicio estará funcionando a plena capacidad, por lo Task.Delay que es básico moverlo mientras esperas un tiempo determinado con el método. De forma predeterminada, se establece en 1 segundo (1000 ms), así que reescríbalo en cualquier momento.

depurar

Puede depurar desde Visual Studio. Tenga la seguridad de que en realidad no estará registrado en el servicio.

Cuando lo ejecutes, aparecerá la consola.

Si el proceso es correcto, puede ver que el archivo se ha creado.

Si desea detener la depuración, cierre la consola.

Si comprueba el registro, puede ver que el proceso de inicio del servicio ha pasado, pero el proceso de terminación no. Para ver la terminación, debe registrarse en el servicio de Windows para verificarla.

emitir

Para poder registrarse en un servicio de Windows, debe publicar el programa. Haga clic con el botón derecho en el proyecto y elija Publicar.

Seleccione Carpetas.

La ubicación de la carpeta es agradable de forma predeterminada.

Se crearán los ajustes de publicación, así que selecciona "Mostrar todos los ajustes".

Configúralo de la siguiente manera:

Nombre del parámetro Valor Comentarios
configuración Versión (predeterminada)
Marco de destino net8.0 (predeterminado)
Modos de implementación Dependencia del marco Por separado, para el entorno de registro de servicios. Si está instalando el tiempo de ejecución de NEt 8, esta configuración es correcta.
Tiempo de ejecución de destino win-x64 Si el sistema operativo es un entorno de 32 bits, seleccione win-x86
Ubicación de destino predeterminado
Creación de un solo archivo EN
Compilación ReadyToRun arbitrario

Después de la configuración, haga clic en el botón "Enviar".

Si en la esquina inferior izquierda se muestra "La publicación se ha realizado correctamente", se ha completado.

El archivo de salida se puede abrir haciendo clic en "Ubicación de destino".

Colocación en el programa e inscripción en los servicios

Inicie sesión en el entorno en el que desea registrar el servicio de Windows con privilegios de administrador.

Copie el archivo publicado en el entorno en el que desea registrarlo como servicio de Windows. Puede colocarlo en cualquier carpeta, pero tenga en cuenta que el servicio de Windows siempre se referirá al programa en esa carpeta.

Además, si el archivo publicado contiene un archivo con la extensión .pdb , no lo copie en un entorno donde pueda ser visto por una persona no especificada porque contiene información de desarrollo.

Una vez que el archivo esté en su lugar, regístrelo como un servicio de Windows. Utilice el comando para registrarse. Haga clic con el botón derecho en el menú Inicio y seleccione "Terminal (Admin)". Sr./Sra. se está ejecutando en un entorno de Windows 11, pero en otros entornos, está bien abrir un símbolo del sistema con privilegios de administrador.

En el caso del terminal, es posible que PowerShell se abra primero, pero es posible que PowerShell no pueda configurarlo correctamente, así que abra el "Símbolo del sistema".

Puede registrarlo en el servicio de Windows con el siguiente comando:

formato

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

Entrada de ejemplo

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

<サービス名> es el nombre que aparece en la lista de servicios de Windows. Puede establecer un nombre para mostrar independiente, pero si no especifica un nombre para mostrar, se mostrará este nombre. También afecta al registro, por lo que se prefieren los nombres alfanuméricos de los servicios.

start=auto es una configuración para iniciar automáticamente el servicio cuando se inicia Windows. Si desea iniciarlo manualmente, elimine esta descripción.

binpath es la ruta completa de los archivos del programa.

Si ejecuta el comando y [SC] CreateService SUCCESS muestra , se realiza correctamente.

Los servicios que registró deben aparecer en la lista.

Inicie el servicio y compruebe su funcionamiento

Si desea ejecutar el servicio, puede iniciarlo desde la pantalla de servicio o con el siguiente comando.

sc start <サービス名>

El comando de parada es el siguiente.

sc stop <サービス名>

Si detiene el servicio, puede comprobar que el proceso de apagado se está ejecutando.

Agregar una descripción al servicio

El campo de descripción del servicio agregado está en blanco, pero puede agregarlo con el siguiente comando.

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

Eliminación de un servicio

Si desea eliminar el servicio, puede hacerlo con el siguiente comando. Debe tener privilegios de administrador en el símbolo del sistema.

sc delete <サービス名>