C# 创建Windows服务方法 C#如何编写Windows Service

来源:这里教程网 时间:2026-02-21 17:40:53 作者:

Windows Service 项目模板在哪?VS 2022 还有吗

Visual Studio 2022 默认已移除「Windows Service (.NET Framework)」项目模板,.NET Core / .NET 5+ 也不再原生支持传统

ServiceBase
托管方式。想用 C# 写 Windows 服务,现在主流路径是:.NET 6+ +
WorkerService
模板 +
Microsoft.Extensions.Hosting.WindowsServices
包。

新建项目时选「Worker Service」,不是「Console App」——虽然底层都是控制台宿主,但

WorkerService
自带
IHostedService
基础结构,更贴近服务生命周期管理。

若必须兼容旧版(如需安装到 Windows Server 2008 或依赖
ServiceController
直接通信),只能用 .NET Framework 4.7.2+ +
ServiceBase
,且需手动创建项目、添加引用
.NET 6+ 的
WorkerService
在 Windows 上可注册为服务,但不支持交互式桌面会话(
AllowServiceToInteractWithDesktop
已废弃)
安装工具统一用
sc.exe
或 PowerShell
New-Service
,不再依赖
InstallUtil.exe
(它在 .NET Core+ 中不可用)

如何让 WorkerService 正确注册为 Windows 服务

核心是两步:修改宿主配置 + 添加 Windows 服务支持包。缺一不可,否则

sc start
会报错 1053(服务未及时响应启动或控制请求)。

先安装 NuGet 包:

dotnet add package Microsoft.Extensions.Hosting.WindowsServices

然后在

Program.cs
中启用 Windows 服务支持:

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<MyBackgroundService>();
// 必须加这行,否则无法作为服务运行
builder.Services.AddWindowsService(options =>
{
    options.ServiceName = "MyAppWorkerService";
});
var host = builder.Build();
host.Run();
options.ServiceName
必须设置,且不能含空格或特殊字符(建议纯字母数字)
不要调用
host.Start()
后再
host.WaitForShutdown()
——
host.Run()
已封装完整服务生命周期
发布时用
dotnet publish -c Release -r win-x64 --self-contained true
,生成独立部署包,避免目标机缺少运行时

服务启动失败常见错误和排查点

最常遇到的是事件查看器里显示「服务没有及时响应启动或控制请求」(错误 1053),本质是宿主初始化卡住或未正确绑定 Windows 服务上下文。

检查是否漏掉
AddWindowsService()
调用 —— 这是最常见疏漏,会导致
Environment.UserInteractive
仍为
true
,服务进程误判为控制台模式
确认程序入口点(
Main
方法)是否直接调用
host.Run()
;若用了
await host.RunAsync()
但没设
async Main
,会编译失败
日志输出默认不写入 Windows 事件日志,需显式添加
builder.Logging.AddEventLog()
并配置
SourceName
服务账户权限不足(比如用 LocalSystem 以外的账户运行,又试图访问网络路径或注册表)—— 临时调试可先设为
LocalSystem
,上线再降权

如何安装、启动、卸载服务(命令行实操)

全部使用管理员权限的 PowerShell 或 CMD,别用普通用户窗口。

安装(假设发布后路径为

C:\MyApp\MyApp.exe
):
sc create MyAppService binPath= "C:\MyApp\MyApp.exe" start= auto obj= "LocalSystem"

注意:

binPath=
后面有空格,
start=
obj=
同理;路径含空格必须用英文双引号包裹整个路径值,而不是只包路径。

启动与验证:

sc start MyAppService
sc query MyAppService

卸载前务必先停止:

sc stop MyAppService
sc delete MyAppService

sc query
STATE
是否为
RUNNING
WIN32_EXIT_CODE
是否为
0x0
如果服务一闪而退,立刻查 Windows 事件查看器 → Windows 日志 → 应用程序,筛选来源为你的
SourceName
.NET Runtime
开发阶段可先以控制台模式运行(不注册服务):直接双击 exe 或
dotnet MyApp.dll
,方便调试日志和异常堆栈

.NET 6+ 的 Windows 服务模型绕过了

ServiceBase
,但生命周期钩子(如启动/停止通知)得靠
IHostedService.StartAsync()/StopAsync()
实现;很多人卡在「服务装上了却没执行业务逻辑」,往往是因为忘了在
StartAsync
里真正启动后台任务(比如
Task.Run
或定时器),或者异常没捕获导致
StartAsync
提前退出。

相关推荐