Windows Service 服务搭配FluentScheduler实现定时任务调度
Windows Service 服务
创建Windows Service 项目
- 创建一个
Windows Service
项目,并将项目名称改为TaskWindowService
- 在解决方案资源管理器内将
Service1.cs
改为TaskService.cs
- 在服务启动和结束时,记录日志
protected override void OnStart(string[] args)
{
LogHelper.Log("服务启动!");
}
protected override void OnStop()
{
LogHelper.Log("服务停止!");
}
- 打开
TaskService
的设计界面,右键“添加安装程序” - 此时软件会生成两个组件,分别为
serviceInstaller1
及serviceProcessInstaller1
- 点击
serviceInstaller1
,在“属性”窗体将ServiceName
改为TaskService
,Description
改为我的服务,StartType
保持为Manual
- 点击
serviceProcessInstaller1
,在“属性”窗体将Account
改为LocalSystem
(服务属性系统级别)
- 鼠标右键点击项目
TaskWindowService
,在弹出的上下文菜单中选择“生成”按钮,到此WindowService
项目搭建完毕
创建安装、启动、停止、卸载服务的Windows窗体
- 新建一个
Windows Form
项目,并命名为WindowsServiceClient
- 添加引用将
TaskWindowService
添加到WindowsServiceClient
中,并将其设置为“启动项目” - 创建安装、启动、停止、卸载 按钮并创建点击事件
string serviceFilePath = $"{Application.StartupPath}\\TaskWindowsService.exe";
string serviceName = "TaskService";
//事件:安装服务
private void button1_Click(object sender, EventArgs e)
{
if (this.IsServiceExisted(serviceName)) this.UninstallService(serviceName);
this.InstallService(serviceFilePath);
}
//事件:启动服务
private void button2_Click(object sender, EventArgs e)
{
if (this.IsServiceExisted(serviceName)) this.ServiceStart(serviceName);
}
//事件:停止服务
private void button4_Click(object sender, EventArgs e)
{
if (this.IsServiceExisted(serviceName)) this.ServiceStop(serviceName);
}
//事件:卸载服务
private void button3_Click(object sender, EventArgs e)
{
if (this.IsServiceExisted(serviceName))
{
this.ServiceStop(serviceName);
this.UninstallService(serviceFilePath);
}
}
//判断服务是否存在
private bool IsServiceExisted(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController sc in services)
{
if (sc.ServiceName.ToLower() == serviceName.ToLower())
{
return true;
}
}
return false;
}
//安装服务
private void InstallService(string serviceFilePath)
{
using (AssemblyInstaller installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = serviceFilePath;
IDictionary savedState = new Hashtable();
installer.Install(savedState);
installer.Commit(savedState);
MessageBox.Show("服务安装成功!");
}
}
//卸载服务
private void UninstallService(string serviceFilePath)
{
using (AssemblyInstaller installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = serviceFilePath;
installer.Uninstall(null);
MessageBox.Show("服务卸载成功!");
}
}
//启动服务
private void ServiceStart(string serviceName)
{
using (ServiceController control = new ServiceController(serviceName))
{
if (control.Status == ServiceControllerStatus.Stopped)
{
control.Start();
MessageBox.Show("服务启动成功!");
}
}
}
//停止服务
private void ServiceStop(string serviceName)
{
using (ServiceController control = new ServiceController(serviceName))
{
if (control.Status == ServiceControllerStatus.Running)
{
control.Stop();
MessageBox.Show("服务停止成功!");
}
}
}
直接运行WindowsServiceClient
项目,并点击“安装服务”会报错提示权限不足。
此时可以打开项目的Debug
文件夹,找到WindowsServiceClient.exe
文件,右键以管理员身份运行。
使用WIN+R
的方式打开运行窗体,并在窗体内输入services.msc
后打开服务,可以找到刚刚安装的TaskService
。
若需要直接运行项目来打开窗体安装服务,则需要使用UAC中Administrator的权限。在WindowsServiceClient
项目中添加“应用程序清单文件”。
打开该文件将asInvoker
修改为requireAdministrator
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
重启项目后就可以直接在VS中安装服务了。
以上内容主要转载自 https://www.cnblogs.com/cncc/p/7170951.html 然后做了一些小改动。
FluentScheduler 定时任务
关于FluentScheduler
详细的介绍可以看下github的说明文档,介绍了所有的调用方式 https://github.com/fluentscheduler/FluentScheduler
- 在
TaskWindowsService
项目中通过nuget
添加FluentScheduler
包
- 在
TaskService
中,服务启动的地方注册定时任务
protected override void OnStart(string[] args)
{
LogHelper.Log("服务启动!");
//每10秒执行一次任务
var registry = new Registry();
registry.Schedule(() =>
{
LogHelper.Log("服务运行中,执行定时任务!");
}).ToRunEvery(10).Seconds();
JobManager.Initialize(registry);
}
重新生成项目->运行->安装服务->运行服务,打开日志文件可以看到定时重新的任务的输出记录。
分类:
C#
标签:
Windows Service
, C#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构