יצירת שירות עבור Windows ב- .NET 8

עודכן דף :
תאריך יצירת דף :

סביבת הפעלה

Visual Studio
  • Visual Studio 2022
.רשת
  • .NET 8
חלונות
  • חלונות 11

דרישות מוקדמות

Visual Studio
  • Visual Studio 2022
.רשת
  • .NET 8
חלונות
  • חלונות 10
  • חלונות 11
שרת Windows
  • Windows 2012 ואילך

תנאי מקדים

  • Visual Studio כבר מותקן

בהתחלה

כאשר אני מנסה ליצור שירות Windows ב- Visual Studio .NET, קיימות רק תבניות .NET Framework. ניתן ליצור אותו גם ב- .NET (Core), והתבנית נקראת "שירות עובד".

במאמר זה, אסביר כיצד להשתמש בכך כדי ליצור, לרשום ולהפעיל שירות Windows. תוכן העיבוד הוא מינימלי, כך שאם תוכל לאשר שהוא פועל כשירות Windows, צור את הפונקציה.

יצירת פרוייקט

הפעל את Visual Studio. בחר צור פרוייקט חדש.

הזן בשדה החיפוש サービス לעיל ולאחר מכן בחר שירות עובדים מהרשימה. "שירותי Windows" הם גירסת .NET Framework, שאין לה גירסת .NET.

שם הפרויקט ומיקומו יכולים להיות שרירותיים. זה לא משפיע על השירות שאתה נרשם אליו.

「. NET 8.0 נבחר, והשאר את ברירות המחדל כדי ליצור אותו.

הפרויקט נוצר.

הוספת ספריות

במצב הראשוני, יש לו רק פונקציית "שירות" ולא פונקציות ספציפיות ל- Windows. הוסף ספריה ששירות Windows יכול להשתמש בה מ- NuGet.

לחץ לחיצה ימנית על יחסי תלות ובחר נהל חבילות NuGet.

בחר בכרטיסיה עיון והזן בשדה החיפוש Microsoft.Extensions.Hosting.WindowsServices . זה יופיע ברשימה, אז להתקין אותו.

לחץ על החל.

הוא נוסף כחבילה.

עריכת תוכניות

הפעם, אצור שירות שמוסיף מעת לעת טקסט לקובץ טקסט כמר / גב'.

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 זה בסיסי להעביר אותו בזמן המתנה זמן מסוים עם השיטה. כברירת מחדל, הוא מוגדר לשנייה אחת (1000ms), אז אנא כתוב אותו מחדש בכל עת.

איתור באגים

באפשרותך לאתר באגים מתוך Visual Studio. היה סמוך ובטוח שלא תירשם בפועל לשירות.

כאשר תפעיל אותו, הקונסולה תופיע.

אם התהליך נכון, באפשרותך לראות שהקובץ נוצר.

אם ברצונך להפסיק את איתור הבאגים, סגור את הקונסולה.

אם תבדוק את היומן, תוכל לראות שתהליך התחלת השירות עבר, אך תהליך הסיום לא עבר. כדי לראות את הסיום, עליך להירשם בפועל לשירות Windows כדי לאמת אותה.

בעיה

כדי שתוכל להירשם לשירות Windows, עליך לפרסם את התוכנית. לחץ באמצעות לחצן העכבר הימני על הפרויקט ובחר פרסם.

בחר תיקיות.

מיקום התיקיה נחמד כברירת מחדל.

הגדרות הפרסום ייווצרו, לכן בחר "הצג את כל ההגדרות".

הגדר אותו באופן הבא:

ערך
הערות של שם פרמטר
תצורה שחרור (ברירת מחדל)
מסגרת יעד net8.0 (ברירת מחדל)
מצבי פריסה תלות במסגרת בנפרד עבור סביבת רישום השירות. אם אתה מתקין את זמן הריצה NEt 8, הגדרה זו בסדר.
זמן ריצה של יעד Win-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 <サービス名>

פקודת העצירה היא כדלקמן.

sc stop <サービス名>

אם תפסיק את השירות, תוכל לוודא שתהליך הכיבוי פועל.

הוספת תיאור לשירות

שדה התיאור של השירות שנוסף ריק, אך באפשרותך להוסיף אותו באמצעות הפקודה הבאה.

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

מחיקת שירות

אם ברצונך למחוק את השירות, באפשרותך לעשות זאת באמצעות הפקודה הבאה. דרושות לך הרשאות מנהל מערכת בשורת הפקודה.

sc delete <サービス名>