ASP.NET 核心 (.Net 6) Web 应用程序在 运行 作为服务时抛出 System.NotSupportedException。 (服务不会启动)

ASP.NET Core (.Net 6) Web Application throws System.NotSupportedException when run as a service. (Service will not start)

当我尝试 运行 我的 .Net Web 应用程序作为 Windows 服务时,它没有启动。如果我只是 运行 可执行文件但在尝试 运行 作为服务时神秘地失败,它会起作用。我已经记录了相关的错误消息并在下面报告了我的解决方案。

事件查看器中出现以下异常。

事件查看器异常

Application: WebApplication5.exe CoreCLR Version: 6.0.222.6406 .NET Version: 6.0.2 Description: The process was terminated due to an unhandled exception. Exception Info: System.NotSupportedException: The content root changed from "C:\Windows\system32" to "C:\Program Files (x86)\My Company\webapp5". Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead. at Microsoft.AspNetCore.Builder.ConfigureHostBuilder.ConfigureHostConfiguration(Action1 configureDelegate) at Microsoft.Extensions.Hosting.HostingHostBuilderExtensions.UseContentRoot(IHostBuilder hostBuilder, String contentRoot) at Microsoft.Extensions.Hosting.WindowsServiceLifetimeHostBuilderExtensions.UseWindowsService(IHostBuilder hostBuilder, Action1 configure) at Microsoft.Extensions.Hosting.WindowsServiceLifetimeHostBuilderExtensions.UseWindowsService(IHostBuilder hostBuilder) at Program.$(String[] args) in C:\Users\Jonathan\source\repos\WebApplication5\WebApplication5\Program.cs:line 10

重建步骤

Program.cs

我的应用程序基于 ASP.NET Core Web API 模板。我按照 https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-6.0&tabs=visual-studio#app-configuration 上的说明将 UseWindowsService() 添加到 Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Host.UseWindowsService();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

部署二进制文件并创建服务

我用 dotnet publish -c Debug --self-contained --runtime win-x64 -p:PublishSingleFile=true

编译了一个二进制文件

将输出复制到目标机器并运行在管理 Powershell

New-Service -Name WebApplication5 -BinaryPathName C:\Users\WDAGUtilityAccount\Desktop\webapp5\WebApplication5.exe

当我尝试启动服务时:

    PS C:> Start-Service WebApp5
    Start-Service : Service 'WebApp5 (WebApp5)' cannot be started due to the following error: Cannot start service WebApp5 on computer '.'.
    At line:1 char:1
    + Start-Service WebApp5
    + ~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service], ServiceCommandException
        + FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand

当我使用服务 GUI 时:

Windows could not start the WebApplication5 service on Local Computer

Error 1053:The service did not respond to the start or control request in a timely fashion.

就像 event-viewer 中的异常建议的那样,我需要在 Program.cs 中使用 non-default 构造函数并在那里设置 ContentRootPath

更改 program.cs 解决了这个问题。

//set ContentRootPath so that builder.Host.UseWindowsService() doesn't crash when running as a service
var webApplicationOptions = new WebApplicationOptions
{
    ContentRootPath = AppContext.BaseDirectory,
    Args = args,
};    
var builder = WebApplication.CreateBuilder(webApplicationOptions);

//All the following code is unchanged from my original program.cs

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Host.UseWindowsService();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

很有魅力!谢谢

添加了一行以设置 url:

builder.WebHost.UseUrls("http://localhost:" + _portNo);