c# 如何创建windows服务

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

Windows 服务项目模板在哪

Visual Studio 2019 及之后版本默认**已移除**

Windows Service
项目模板。不是你没找到,是它真没了。若用较新版本新建项目,
Windows Forms App
Console App
都不能直接当服务跑——它们缺少服务生命周期管理入口。

正确路径是:新建项目 → 搜索 “

Worker Service
” → 选中 .NET 6+ 的模板。这是微软当前推荐的 Windows 服务实现方式,底层基于
IHostedService
,比老式
ServiceBase
更轻量、更可控。

老式
ServiceBase
仍可用,但需手动添加
System.ServiceProcess.ServiceController
NuGet 包(.NET Core/.NET 5+)
Worker Service
模板生成的是跨平台主机,但部署到 Windows 并注册为服务时,行为完全等同传统 Windows 服务
不要试图在 WinForms 或 WPF 项目里“加个服务类”就完事——GUI 线程模型和服务 SCM(Service Control Manager)不兼容,启动必失败

如何把 Worker Service 注册为系统服务

核心命令是

sc.exe
,必须以管理员权限运行。注册前确保已发布为自包含(self-contained)或框架依赖(framework-dependent)可执行文件。

假设发布后路径为

C:MyServiceMyService.exe
,执行:

sc create "MyServiceName" binPath= "C:MyServiceMyService.exe" start= auto obj= "LocalSystem"

注意:

binPath=
后面**必须有空格**,且路径含空格时要加英文双引号;
obj=
指定运行账户,
LocalSystem
权限高但风险大,生产环境建议用专用服务账户。

启动服务:
sc start "MyServiceName"
查看状态:
sc query "MyServiceName"
(返回
STATE: 4 RUNNING
才算成功)
卸载服务:
sc delete "MyServiceName"
(删除前先
sc stop
日志输出默认写入 Windows 事件查看器 → “Windows 日志 → 应用程序”,不是控制台

为什么服务启动后立即退出

最常见原因是

Program.cs
中的主机未被阻塞,进程自然结束。Worker Service 默认使用
Host.CreateDefaultBuilder()
,但若你删了
.Run()
或替换成
.Start()
就会出问题。

正确结构必须包含:

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<MyBackgroundService>();
    })
    .Build();
<p>host.Run(); // ← 这行不能少,也不能换成 Start()
host.Start()
是异步启动,不阻塞主线程,进程立刻退出
host.Run()
内部调用
StartAsync()
+ 阻塞等待 Ctrl+C 或服务停止信号
若需调试,可在
Main
方法末尾加
Console.ReadLine()
(仅开发时),但正式部署必须用
Run()
检查
MyBackgroundService
ExecuteAsync(CancellationToken)
是否抛异常——未捕获异常会导致服务崩溃并被 SCM 标记为“已停止”

如何让服务能访问网络或文件系统

Windows 服务默认以

LocalSystem
账户运行,对本地资源权限足够,但对网络路径(如
\servershare
)、映射驱动器、交互式桌面(UI)、用户配置文件(
%USERPROFILE%
)均无访问权。

访问 UNC 路径:改用域名账户(
DOMAINsvcuser
),并在目标服务器上授予权限;或改用
\ipshare
并启用 SMB 签名兼容模式
读写用户目录:不要硬编码
%USERPROFILE%
,改用
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
需要弹窗或操作桌面?别这么做。Windows 服务设计上禁止交互;如真需 GUI,请改用启动类型为
Interactive
的旧式服务(不推荐,Win10/11 已限制)
调试时看到“拒绝访问”错误,先查事件查看器里的详细异常堆栈,再确认服务账户权限,而不是盲目加
RequireAdministrator

服务注册和调试的坑集中在权限、路径、生命周期三处。哪怕代码逻辑完全正确,

sc create
少个空格、
host.Run()
写成
Start()
、服务账户没权限访问目标文件夹,都会导致“安装成功但无法启动”。

相关推荐