You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何通过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中,你可以:

  1. 写一个简单的ASP.NET Core API读取表中的数据,供前端调用;
  2. 前端使用Chart.js、ECharts等可视化库,展示任务的执行成功率、错误次数、平均耗时等核心指标;
  3. 也可以直接用Power BI连接SQL Server,快速生成可视化仪表板,不需要自己编写前端代码。

内容的提问来源于stack exchange,提问作者Vijaya Malla

火山引擎 最新活动