ایجاد یک سرویس برای ویندوز در دات نت 8

صفحه به روز شده :
تاریخ ایجاد صفحه :

محیط عملیاتی

ویژوال استودیو
  • ویژوال استودیو 2022
.خالص
  • دات نت 8
ویندوز
  • ویندوز 11

پیش نیازها

ویژوال استودیو
  • ویژوال استودیو 2022
.خالص
  • دات نت 8
ویندوز
  • ویندوز 10
  • ویندوز 11
ویندوز سرور
  • ویندوز 2012 یا بالاتر

پیش شرط

  • ویژوال استودیو قبلا نصب شده است

در ابتدا

وقتی می خواهم یک سرویس ویندوز در ویژوال استودیو دات نت ایجاد کنم، فقط قالب های NET Framework وجود دارد. همچنین می توان آن را در دات نت (Core) ایجاد کرد و الگو "Worker Service" نام دارد.

در این مقاله نحوه استفاده از آن برای ایجاد، ثبت و اجرای سرویس ویندوز را توضیح خواهم داد. محتوای پردازش حداقل است، بنابراین اگر می توانید تأیید کنید که به عنوان یک سرویس ویندوز اجرا می شود، لطفا عملکرد را ایجاد کنید.

یک پروژه ایجاد کنید

ویژوال استودیو را راه اندازی کنید. ایجاد یک پروژه جدید را انتخاب کنید.

در サービス قسمت جستجوی بالا وارد شوید و سپس Worker Service را از لیست انتخاب کنید. "Windows Services" نسخه .NET Framework است که نسخه دات نت ندارد.

نام و مکان پروژه می تواند دلخواه باشد. این بر سرویسی که در آن ثبت نام می کنید تأثیر نمی گذارد.

「. NET 8.0 انتخاب شده است و پیش فرض ها را برای ایجاد آن بگذارید.

پروژه ایجاد شده است.

افزودن کتابخانه ها

در حالت اولیه، فقط یک تابع "سرویس" دارد و هیچ عملکردی خاص ویندوز ندارد. کتابخانه ای اضافه کنید که می تواند توسط یک سرویس ویندوز از NuGet استفاده شود.

روی Dependencies کلیک راست کرده و Manage NuGet Packages را انتخاب کنید.

تب Browse را انتخاب کرده و در Microsoft.Extensions.Hosting.WindowsServices قسمت جستجو وارد کنید. در لیست ظاهر می شود، پس آن را نصب کنید.

روی اعمال کلیک کنید.

به عنوان یک بسته اضافه شد.

ویرایش برنامه ها

این بار، من سرویسی ایجاد می کنم که به صورت دوره ای متن را به عنوان آقای/خانم به یک فایل متنی اضافه می کند.

Program.cs

عملکرد سرویس ویندوز را به صورت زیر اضافه کنید:

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 این روش با sstopToken به حلقه زدن ادامه می دهد تا زمانی while که برای لغو پرچم گذاری شود. آنچه while را که می خواهید در حین اجرای سرویس پردازش شود اضافه کنید. با این حال، اگر فقط فرآیندی را که می خواهید جابجا کنید بنویسید، سرویس با ظرفیت کامل اجرا می شود، بنابراین Task.Delay جابجایی آن در حالی که مدت زمان مشخصی با روش منتظر می مانید، ضروری است. به طور پیش فرض، روی 1 ثانیه (1000 میلی ثانیه) تنظیم شده است، بنابراین لطفا در هر زمان آن را بازنویسی کنید.

اشکال زدایی

می توانید از ویژوال استودیو اشکال زدایی کنید. مطمئن باشید که در واقع در این سرویس ثبت نام نخواهید کرد.

وقتی آن را اجرا می کنید، کنسول ظاهر می شود.

اگر فرآیند صحیح باشد، می بینید که فایل ایجاد شده است.

اگر می خواهید اشکال زدایی را متوقف کنید، کنسول را ببندید.

اگر گزارش را بررسی کنید، می بینید که فرآیند شروع سرویس گذشته است، اما فرآیند خاتمه این کار را انجام نداده است. برای مشاهده فسخ، باید در واقع در سرویس ویندوز ثبت نام کنید تا آن را تأیید کنید.

شماره

برای اینکه بتوانید در یک سرویس ویندوز ثبت نام کنید، باید برنامه را منتشر کنید. روی پروژه کلیک راست کرده و Publish را انتخاب کنید.

پوشه ها را انتخاب کنید.

مکان پوشه به طور پیش فرض خوب است.

تنظیمات انتشار ایجاد می شود، بنابراین "نمایش همه تنظیمات" را انتخاب کنید.

آن را به صورت زیر تنظیم کنید:

نام
پارامتر توضیحات مقدار
پیکربندی انتشار (پیش فرض)
چارچوب هدف net8.0 (پیش فرض)
حالت های استقرار وابستگی به چارچوب به طور جداگانه برای محیط ثبت سرویس. اگر زمان اجرا NEt 8 را نصب می کنید، این تنظیم خوب است.
زمان اجرا هدف Win-x64 اگر سیستم عامل یک محیط 32 بیتی است، win-x86 را انتخاب کنید
مکان هدف پیش فرض
ایجاد یک فایل واحد در
کامپایل ReadyToRun خودسرانه

پس از تنظیم، روی دکمه "ارسال" کلیک کنید.

اگر «انتشار موفقیت آمیز بود» در گوشه پایین سمت چپ نمایش داده شود، کامل است.

فایل خروجی را می توان با کلیک بر روی "مکان هدف" باز کرد.

قرار دادن برنامه و ثبت نام در خدمات

وارد محیطی شوید که می خواهید سرویس ویندوز را با امتیازات مدیر ثبت کنید.

فایل منتشر شده را در محیطی که می خواهید آن را به عنوان سرویس ویندوز ثبت کنید، کپی کنید. می توانید آن را در هر پوشه ای قرار دهید، اما به خاطر داشته باشید که سرویس ویندوز همیشه به برنامه موجود در آن پوشه مراجعه می کند.

همچنین، اگر فایل منتشر شده حاوی فایلی با پسوند .pdb است، آن را در محیطی که توسط یک شخص نامشخص قابل مشاهده باشد کپی نکنید زیرا حاوی اطلاعات توسعه است.

پس از قرار گرفتن فایل، آن را به عنوان یک سرویس ویندوز ثبت کنید. از دستور برای ثبت نام استفاده کنید. روی منوی Start کلیک راست کرده و "Terminal (Admin)" را انتخاب کنید. Mr./Ms. در یک محیط ویندوز 11 اجرا می شود، اما در محیط های دیگر، باز کردن یک خط فرمان با امتیازات مدیر اشکالی ندارد.

در مورد ترمینال، ممکن است ابتدا PowerShell باز باشد، اما PowerShell ممکن است نتواند آن را به درستی تنظیم کند، بنابراین "Command Prompt" را باز کنید.

با دستور زیر می توانید آن را در سرویس ویندوز ثبت کنید:

فرمت

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

ورودی نمونه

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

<サービス名> نامی است که در لیست سرویس های ویندوز ظاهر می شود. می توانید یک نام نمایشی جداگانه تنظیم کنید، اما اگر نام نمایشی را مشخص نکنید، این نام نمایش داده می شود. همچنین بر رجیستری تأثیر می گذارد، بنابراین نام خدمات الفبایی ترجیح داده می شود.

start=auto تنظیماتی برای شروع خودکار سرویس هنگام راه اندازی ویندوز است. اگر می خواهید آن را به صورت دستی شروع کنید، این توضیحات را حذف کنید.

binpath مسیر کامل فایل های برنامه است.

اگر دستور و [SC] CreateService SUCCESS نمایش را اجرا کنید، موفقیت آمیز است.

خدماتی که ثبت نام کرده اید باید در لیست ظاهر شوند.

سرویس را راه اندازی کنید و عملکرد آن را بررسی کنید

اگر می خواهید سرویس را اجرا کنید، می توانید آن را از صفحه سرویس یا با دستور زیر راه اندازی کنید.

sc start <サービス名>

دستور توقف به شرح زیر است.

sc stop <サービス名>

اگر سرویس را متوقف کنید، می توانید بررسی کنید که فرآیند خاموش شدن در حال اجرا است.

افزودن توضیحات به سرویس

فیلد توضیحات سرویس اضافه شده خالی است، اما می توانید آن را با دستور زیر اضافه کنید.

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

حذف یک سرویس

اگر می خواهید سرویس را حذف کنید، می توانید این کار را با دستور زیر انجام دهید. شما باید امتیازات مدیر را در خط فرمان داشته باشید.

sc delete <サービス名>