Windows服务是运行在Windows操作系统后台的应用程序,无需用户登录即可自动运行,适合实现定时任务、数据监听、后台处理等场景。使用C#开发Windows服务可以通过.NET框架提供的原生类库快速实现,开发完成后只需简单配置即可注册为系统服务并设置自启。

C#开发Windows服务的前期准备
首先需要安装Visual Studio开发工具,确保勾选了.NET桌面开发相关的工作负载,因为Windows服务项目依赖.NET Framework的相关组件。本文示例基于.NET Framework 4.7.2,使用Visual Studio 2022进行演示,其他版本的操作流程基本一致。
创建Windows服务项目
打开Visual Studio,点击创建新项目,在项目模板搜索框中输入Windows服务,选择Windows 服务(.NET Framework)模板,点击下一步。
配置项目名称和保存路径,点击创建后,系统会自动生成基础的服务项目结构,默认会包含一个继承ServiceBase的服务类,以及Program.cs入口文件。
编写服务核心逻辑
默认生成的服务类名为Service1,我们可以修改类名和服务的显示名称,然后重写OnStart和OnStop方法,这两个方法分别是服务启动和停止时执行的回调逻辑。
以下是一个简单的服务示例,服务启动后会每隔5秒向本地日志文件写入一条记录,服务停止时停止写入:
using System;
using System.IO;
using System.ServiceProcess;
using System.Threading;
namespace WindowsServiceDemo
{
public partial class DemoService : ServiceBase
{
// 定时器用于执行定时任务
private Timer workTimer;
// 日志文件路径
private readonly string logPath = @"C:ServiceLogservice_log.txt";
// 标记服务是否运行中
private bool isRunning = false;
public DemoService()
{
InitializeComponent();
// 设置服务名称,这个名称会用于服务注册和启动
this.ServiceName = "DemoWindowsService";
}
// 服务启动时的回调方法
protected override void OnStart(string[] args)
{
isRunning = true;
// 确保日志目录存在
string logDir = Path.GetDirectoryName(logPath);
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
// 写入启动日志
File.AppendAllText(logPath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 服务启动{Environment.NewLine}");
// 初始化定时器,每隔5秒执行一次任务
workTimer = new Timer(DoWork, null, 0, 5000);
}
// 定时执行的任务逻辑
private void DoWork(object state)
{
if (!isRunning)
{
return;
}
string logContent = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 服务正在运行,执行定时任务{Environment.NewLine}";
File.AppendAllText(logPath, logContent);
}
// 服务停止时的回调方法
protected override void OnStop()
{
isRunning = false;
workTimer?.Dispose();
File.AppendAllText(logPath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 服务停止{Environment.NewLine}");
}
}
}
注意:如果项目中没有自动生成InitializeComponent方法,可以手动添加一个内部方法初始化服务的基础属性,代码如下:
private void InitializeComponent()
{
this.CanShutdown = true;
this.CanStop = true;
this.CanPauseAndContinue = false;
}
添加服务安装组件
要让Windows服务可以被系统注册,需要添加服务安装组件。双击服务类文件,切换到设计视图,右键点击空白处,选择添加安装程序。
系统会自动生成ProjectInstaller类,其中包含两个核心组件:serviceInstaller1和serviceProcessInstaller1。
我们需要配置这两个组件的属性:
- serviceProcessInstaller1的Account属性设置为LocalSystem,这样服务会以系统账户运行,拥有较高的权限,避免权限不足导致的运行问题。
- serviceInstaller1的ServiceName属性需要和之前服务类里设置的ServiceName保持一致,这里设置为DemoWindowsService。
- serviceInstaller1的DisplayName属性设置为服务在系统服务列表中的显示名称,比如可以设置为演示Windows服务。
- serviceInstaller1的Description属性设置为服务的描述信息,方便后续管理时识别服务用途。
- serviceInstaller1的StartType属性设置为Automatic,这样服务注册后会默认设置为自动启动,也就是后台自启的效果。
编译生成服务项目
配置完成后,右键点击项目,选择生成,如果编译没有错误,会在项目的binDebug或者binRelease目录下生成对应的exe文件,这个exe文件就是服务程序的主文件,后续注册服务时会用到这个路径。
注册Windows服务并设置自启
Windows服务需要通过系统工具进行注册,常用的工具是sc命令和InstallUtil工具,这里介绍两种常用的注册方式。
使用sc命令注册服务
sc是Windows系统自带的命令行工具,可以直接用于创建、启动、停止和删除服务。首先需要以管理员身份打开命令提示符,然后执行以下命令:
sc create DemoWindowsService binPath= "C:WindowsServiceDemoWindowsServiceDemobinReleaseWindowsServiceDemo.exe" start= auto
命令说明:
- DemoWindowsService是服务的名称,需要和之前配置的服务名称一致。
- binPath=后面是服务exe文件的完整路径,注意binPath=后面有一个空格,路径需要用英文双引号包裹。
- start= auto表示设置服务为自动启动,也就是后台自启,如果需要手动启动可以设置为demand。
执行命令后如果提示CreateService 成功,说明服务已经注册成功,此时打开系统的服务管理界面(运行services.msc),就能看到名为演示Windows服务的条目,启动类型已经设置为自动。
使用InstallUtil工具注册服务
InstallUtil是.NET框架提供的服务安装工具,路径一般在C:WindowsMicrosoft.NETFramework64v4.0.30319InstallUtil.exe,不同系统版本路径可能略有差异。
以管理员身份打开命令提示符,执行以下命令:
C:WindowsMicrosoft.NETFramework64v4.0.30319InstallUtil.exe "C:WindowsServiceDemoWindowsServiceDemobinReleaseWindowsServiceDemo.exe"
执行成功后,服务也会被注册到系统中,之前我们在安装组件里已经设置了StartType为Automatic,所以注册后默认就是自动启动,也就是后台自启状态。
服务的启动、停止和卸载
服务注册完成后,可以通过以下方式管理:
- 启动服务:运行services.msc打开服务列表,找到对应服务右键点击启动,或者使用命令sc start DemoWindowsService。
- 停止服务:右键点击服务选择停止,或者执行命令sc stop DemoWindowsService。
- 卸载服务:如果需要删除服务,先停止服务,然后执行命令sc delete DemoWindowsService,或者使用InstallUtil的卸载命令:C:WindowsMicrosoft.NETFramework64v4.0.30319InstallUtil.exe /u "服务exe路径"。
常见问题及解决方法
开发和使用Windows服务时可能会遇到一些常见问题:
- 服务注册失败:检查是否以管理员身份运行命令提示符,检查exe路径是否正确,检查服务名称是否已经存在。
- 服务启动后马上停止:一般是OnStart方法里出现了未捕获的异常,可以在OnStart方法里添加异常捕获,将错误信息写入日志排查问题。
- 服务没有写入日志的权限:如果日志路径在C盘根目录等系统目录,普通权限可能无法写入,可以修改日志路径到非系统目录,或者给对应目录添加写入权限。
注意:开发Windows服务时,不要直接在Visual Studio里按F5运行,因为Windows服务不能通过普通应用程序的方式直接启动,必须通过系统服务管理器或者命令行启动。