.NET 6调用UseWindowsService()抛出NotSupportedException异常
问题复现
Program.cs 原始代码
var builder = WebApplication.CreateBuilder(args); builder.Host.UseWindowsService(); // Add services to the container. builder.Services.AddGrpc(); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGet("/", () => "error"); app.Run();
引用NuGet包
- Grpc.AspNetCore(2.47.0)
- Microsoft.Extensions.Hosting.WindowsServices (6.0.0)
错误日志
Application: PartReservationGrpc.exe CoreCLR Version: 6.0.622.26707
.NET Version: 6.0.6 Description: The process was terminated due to an unhandled exception. Exception Info: System.NotSupportedException: The content root changed from "C:\windows\system32" to "D:\CMAP\iceman\partreservation". 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\WuJ22\source\Workspaces\C5CG2133PXF\gRPC\PartReservation\PartReservation\PartReservationGrpc\Program.cs:line 33
报错原因
这是.NET 6+最小托管模型的明确行为限制:WebApplicationBuilder初始化完成后,不允许通过builder.Host属性修改主机配置。而UseWindowsService()内部逻辑会自动修改主机内容根路径——Windows服务默认工作目录是C:\Windows\system32,方法会把路径改成服务EXE所在的实际部署目录,这个修改动作直接触发了NotSupportedException。
修复方法
直接调整Program.cs代码,按照错误提示使用WebApplicationOptions在初始化Builder时提前指定内容根路径,同时将Windows服务注册逻辑从builder.Host迁移到服务集合注册即可:
// 初始化Builder时提前传入配置,指定内容根路径和启动参数 var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = args, ContentRootPath = AppContext.BaseDirectory }); // 替换原来的builder.Host.UseWindowsService(),使用服务集合的扩展方法注册Windows服务 builder.Services.AddWindowsService(); // 其余服务注册、中间件配置代码保持不变 builder.Services.AddGrpc(); var app = builder.Build(); app.MapGrpcService<GreeterService>(); app.MapGet("/", () => "error"); app.Run();
修改完成后重新编译发布,再注册启动Windows服务即可正常运行。
注意:6.0.0及以上版本的Microsoft.Extensions.Hosting.WindowsServices包已经自带AddWindowsService()扩展方法,不需要额外升级依赖。
内容的提问来源于stack exchange,提问作者Johnny Wu

