踩坑 Windows 服務來宿主 .NET 程序

本文所指的 .NET 程序爲 .NET6 的程序。因爲 .NET 的版本更新很快,所以方式、方法也有變化,所以網上搜到的方法有些也過時了。以下是最近我實踐下來的一點心得(坑)。
上一篇說到 不安裝運行時運行 .NET 程序 後我們的程序已經只有一個 dll/exe 了,但是在 windows 上運行的時候會是一個控制檯程序,很容易人不小心關閉了。所以想着把我們的程序部署成 windows 服務,這樣不會誤關,重啓服務器的時候也會自動啓動。所以最近折騰了一下把 .NET 程序,特別是 ASP.NET Core 程序部署爲 windows 服務。本來以爲網上隨便搜一搜就很容易,事實上沒想得這麼美好。

Worker Service

如果你的服務只想執行一些後臺任務,比如定時任務,並不提供網站的服務。那麼使用 Worker service 項目模板新建一個項目是最合適的。

新建完項目後使用 nuget 安裝:

Microsoft.Extensions.Hosting.WindowsServices

修改 program.cs 文件

using WorkerService1;

IHost host = Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
    })
    .Build();

await host.RunAsync();

其中就只添加一句 UseWindowsService 就可以了。
編譯之後使用 sc 命令就可以註冊爲服務了。

sc create "wsTest" binPath=wsTest.exe
sc start "wsTest"
pause

我們把它寫成一個 bat 文件方便執行。使用管理權限運行這個 bat 文件服務會被註冊並且直接運行:

ASP.NET Core

以上嘗試了一下 worker service 模式註冊爲服務,感覺簡單的很。但是下面把 ASP.NET Core 程序註冊爲服務的時候就沒那麼簡單啦。我查了一些文章,寫的時間有些早了,所以還是安照微軟官方的文檔 Host ASP.NET Core in a Windows Service 的提示來操作。這篇文章雖然叫 Host ASP.NET Core in a Windows Service ,但其實裏面的內容說的是上面的 worker service 。當按照上面的步驟嘗試把 asp.net core 程序部署爲服務的時候死活起不來,一直報未找到文件的異常。
我們新建一個最簡單的 asp.net core 程序來演示一下:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Host.UseWindowsService();

var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
await app.RunAsync();

這是一個最簡單的 asp.net core razor pages 程序。我們按照文檔安裝擴展包:

Microsoft.Extensions.Hosting.WindowsServices

然後調用 UseWindowsService 方法

builder.Host.UseWindowsService();

同樣使用 sc 命令註冊爲服務並運行它。很遺憾它會報錯。

經過多種嘗試方法都不行。最後翻了一下微軟倉庫裏的 sample 代碼才發現原來他們自己的 sample 代碼裏多了幾行代碼 。

注意下面的代碼了啊 !!!

在構建 builder 的時候需要多傳幾個參數:

var options = new WebApplicationOptions
{
    Args = args,
    ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
};
var builder = WebApplication.CreateBuilder(options);

只要使用這段代碼來構建 builder ,服務就可以順利的運行起來。根據以往的經驗,可能還是作爲服務運行的時候程序根目錄的問題,通過以上方法來指定 AppContext.BaseDirectory 來作爲程序的根目錄,不然就有可能被定位到 system32 目錄下。
吐槽。。。雖然解決方案很簡單,但是微軟沒有在文檔裏把這麼關鍵的代碼給些出來,着實有點坑啊,辛虧現在代碼都在 github 上,很容易翻到,不然得折騰死人。

PS

就在今天2022/09/02微軟的英文文檔已經更新了示例代碼,中文版還沒更新:
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-6.0&tabs=visual-studio#app-configuration-1

關注我的公衆號一起玩轉技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章