如何通过C#编程读取Windows Server任务计划程序的作业历史日志
当然可以用C#实现计划任务日志的导出与存储!
我之前帮不少开发者处理过类似需求,下面给你拆解具体的实现方案,包含代码示例和关键注意点:
一、读取计划任务历史记录的两种常用方法
计划任务的运行历史本质上存储在Windows事件日志中,你可以通过两种方式获取这些数据:
1. 使用Task Scheduler Managed Wrapper(封装库,更易用)
这个库是对原生Windows Task Scheduler API的友好封装,不需要自己处理复杂的COM调用。
首先通过NuGet安装包:
Install-Package TaskScheduler
然后编写代码遍历任务并获取历史记录:
using System; using TaskScheduler; class TaskLogReader { static void Main() { // 连接到本地任务计划服务 using (var ts = new TaskService()) { // 遍历所有任务(你可以指定特定文件夹,比如ts.RootFolder.GetTasks(true)) foreach (var task in ts.RootFolder.GetTasks(true)) { Console.WriteLine($"任务名称: {task.Name}"); // 获取任务的历史记录事件 foreach (var eventLogEntry in task.History) { // 过滤你需要的时间范围:每晚21:00到午夜 if (eventLogEntry.TimeCreated >= DateTime.Today.AddHours(21) && eventLogEntry.TimeCreated <= DateTime.Today.AddDays(1)) { Console.WriteLine($"时间: {eventLogEntry.TimeCreated}, 事件ID: {eventLogEntry.Id}, 描述: {eventLogEntry.Message}"); // 这里可以把数据存入变量,后续写入文件或数据库 } } } } } }
2. 直接查询Windows事件日志(原生方式,无需额外依赖)
如果不想引入第三方库,可以直接查询Microsoft-Windows-TaskScheduler/Operational事件日志,这是计划任务日志的存储位置。
示例代码:
using System; using System.Diagnostics.Eventing.Reader; class EventLogTaskReader { static void Main() { // 动态生成前一天21:00到当天00:00的时间范围 var startDate = DateTime.Today.AddDays(-1).AddHours(21); var endDate = DateTime.Today; var queryString = $"*[System[Provider[@Name='Microsoft-Windows-TaskScheduler'] and TimeCreated[@SystemTime >= '{startDate:o}' and @SystemTime <= '{endDate:o}']]]"; var query = new EventLogQuery( "Microsoft-Windows-TaskScheduler/Operational", PathType.LogName, queryString ); using (var reader = new EventLogReader(query)) { EventRecord record; while ((record = reader.ReadEvent()) != null) { // 解析任务名称(从事件属性中提取) var taskName = record.Properties[0].Value.ToString(); Console.WriteLine($"任务名称: {taskName}, 时间: {record.TimeCreated}, 事件ID: {record.Id}, 描述: {record.FormatDescription()}"); } } } }
注意:运行这段代码需要管理员权限,因为读取Operational日志需要相应权限。
二、将日志数据保存到SQL Server或文本文件
1. 保存到文本文件
这是最简单的方式,直接用StreamWriter写入:
using System.IO; void SaveToTextFile(string filePath, string taskName, DateTime executionTime, int eventId, string eventMessage) { var logContent = $"[{executionTime:yyyy-MM-dd HH:mm:ss}] 任务: {taskName} | 事件ID: {eventId} | 描述: {eventMessage}"; using (var writer = new StreamWriter(filePath, append: true)) { writer.WriteLine(logContent); } } // 使用示例 SaveToTextFile(@"C:\TaskLogs\DailyTaskHistory.txt", "备份任务", DateTime.Now, 100, "任务执行成功");
2. 保存到SQL Server
首先创建存储日志的表:
CREATE TABLE TaskExecutionLogs ( LogId INT IDENTITY(1,1) PRIMARY KEY, TaskName NVARCHAR(255) NOT NULL, ExecutionTime DATETIME NOT NULL, EventId INT NOT NULL, EventMessage NVARCHAR(MAX) NOT NULL, CreatedAt DATETIME DEFAULT GETDATE() );
然后用C#代码插入数据:
using System.Data.SqlClient; void SaveToSqlServer(string connectionString, string taskName, DateTime executionTime, int eventId, string eventMessage) { var sql = @"INSERT INTO TaskExecutionLogs (TaskName, ExecutionTime, EventId, EventMessage) VALUES (@TaskName, @ExecutionTime, @EventId, @EventMessage)"; using (var conn = new SqlConnection(connectionString)) { conn.Open(); using (var cmd = new SqlCommand(sql, conn)) { cmd.Parameters.AddWithValue("@TaskName", taskName); cmd.Parameters.AddWithValue("@ExecutionTime", executionTime); cmd.Parameters.AddWithValue("@EventId", eventId); cmd.Parameters.AddWithValue("@EventMessage", eventMessage); cmd.ExecuteNonQuery(); } } }
三、适配你的需求:每晚21:00到午夜的任务
- 可以在代码中动态生成时间范围,比如获取前一天的21:00到当天00:00,避免硬编码日期;
- 建议把这个导出程序做成一个计划任务,每天凌晨00:30自动运行,导出前一晚的日志数据,无需手动触发。
四、展示到仪表板的建议
既然数据已经存在SQL Server中,你可以:
- 写一个简单的ASP.NET Core API读取表中的数据,供前端调用;
- 前端使用Chart.js、ECharts等可视化库,展示任务的执行成功率、错误次数、平均耗时等核心指标;
- 也可以直接用Power BI连接SQL Server,快速生成可视化仪表板,不需要自己编写前端代码。
内容的提问来源于stack exchange,提问作者Vijaya Malla




