.NET 6學習筆記(2)——通過Worker Service創建Windows Service
通過Visual Studio中的Windows Service模板,我么可以創建.NET Framework版本的Windows Service,網路上對此已有詳細且豐富的各路教程。但在我們升級到.NET Core 3.1或.NET 6後(這裡僅討論兩個LTS版本),情況發生了相當大的變化。我們需要根據新的Worker Service模板,基於BackgroundService這個類來創建最新版本的Windows Service。
某軟的官方文檔更新的很快,文檔中列出的創建Windows Service的必要條件都已經是6.0或更新。那是不是說.NET Core 3.1就無法創建呢?答案當然不是。今天我們就稍作修改,創建3.1版本的Windows Service。
.NET Core 3.1作為LTS(Long-term support)版本,是存在大量基於該版本的生產項目的,有時候條件不允許立刻升級到VS2022和.NET 6.0。所以本篇我們將使用VS2019,首先找到Worker Service模板,如果我們仔細觀察,會發現相較於傳統的Windows,更多了Linux和macOS的支援。
點擊兩次Next按鈕後,選擇.NET Core 3.1版本創建工程。默認僅包含Program和Worker兩個cs文件。接下來我們通過NuGet安裝Microsoft.Extensions.Hosting.WindowsService包。最新的版本是6.0,且同時依賴6.0版的Microsoft.Extension.Hosting。這裡我們有兩個選擇,第一是在NuGet介面的下拉框中,選擇安裝3.1.17版本的WindowsService包,保持和默認Hosting包的版本相同。第二是將兩者都升級到最新的6.0版本。所幸.NET的向後兼容做的不錯,在這裡我選擇升級。在完成後的簡單測試中,無論是部署在.NET 6 Runtime或.NET Core 3.1 Runtime的機器上,均可正常工作。當前狀態應該如下圖所示。
此時我們可以開始創建業務類了,就是你想用Service干點啥,在本篇的示例中,我只想躺平……疫情期間,不要用眼過度和上頭648充值抽卡,打遊戲實在是極其健康的選擇了。
public class LieFlatService { public static int Count { get; set; } public string LieFlat() { return $"Lie flat and play PS4 & Switch... {++Count}"; } }
接著我們通過繼承自BackgrounService的Worker類來調用LieFlatService實現躺平。真的是啥也不幹,就是每隔一秒宣告一下躺平。
public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; private readonly LieFlatService _lieFlatSrvice; public Worker(LieFlatService lieFlatService, ILogger<Worker> logger) { _lieFlatSrvice = lieFlatService; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { string message = _lieFlatSrvice.LieFlat(); _logger.LogWarning(message); _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); } } }
然後我們還要修改一下Program類,通過UseWindowsService擴展方法將我們這個Console程式配置成Windows Service類型。如果我們之前選擇WindowsServices 3.1的包,這裡就不能方便的設置SeviceName了,其他倒是沒啥區別。在CreateHostBuilder方法中,記得註冊Worker和LieFlatService供.NET內置的依賴注入(Dependency Injection)框架使用。
public class Program { public static void Main(string[] args) { CreateHostBuilder(args) .UseWindowsService(o => { o.ServiceName = "Lie Flat Service"; }) .Build() .Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); services.AddSingleton<LieFlatService>(); }); }
程式碼部分至此就全部完成了。相對於.NET Framework的Windows Service,調試起來要容易的多,就直接當成Console程式Debug就行了。部署的操作也很簡單,首先在project文件上右鍵選擇發布到文件夾。
通常默認的發布配置就可以了,點擊發布按鈕之後,會在項目的bin\Release\netcoreapp3.1\win-x64\publish\目錄下生成如下文件。如果修改發布文件選擇Self Contained,則可以脫離對部署環境是否安裝.NET的依賴,缺點就是會生成一大堆文件。
我們可以將publish文件夾拷貝到想要的位置,然後用admin許可權打開PowerShell,通過命令行來創建Windows Service。
sc.exe create "Lie Flat Service" binpath="C:\Users\dell\Desktop\publish\NetCoreWorkerService.exe"
此時打開Services介面,將創建的Lie Flat Service啟動。
再打開檢查Event Viewer檢查Windows Logs,就可以發現Lie Flat Service發出的躺平宣言了。
刪除Windows Service需要通過stop和delete兩個命令。
本篇我們介紹了如何在.NET Core 3.1(.NET 6.0也幾乎相同)的環境下創建Windows Service。同時.NET 4.5.2, .NET 4.6和.NET 4.6.1將於2022年4月26日終止支援。升級吧同學們。
示例程式碼:
//github.com/manupstairs/NetCoreWorkerService
manupstairs/WorkerServiceTest1 (gitee.com)
以下鏈接,是MS Learn上Windows開發的入門課程,單個課程三十分鐘到60分鐘不等,想要補充基礎知識的同學點這裡:
開始使用 Visual Studio 開發 Windows 10 應用