LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[点晴永久免费OA]Windows系统日志查询工具v1.5

admin
2026年4月3日 17:13 本文热度 41

分享一个自己做的一款轻量级的 Windows 事件日志查询工具,提供友好的界面,
可以让你一键筛选所需事件,并利用分层智能缓存技术,实现秒级响应,即使查询几个月的数据也能流畅体验。
本工具其实特意为了查询开关机来设计的,最后不知咋的就变成下面这样了。。。。
系统日志查询工具 v1.5.exe,已更新,欢迎提出意见,求个大佬教我怎么列头居中。

 

1.5 主要更新:

1. 结果内搜索:在已查询结果中快速过滤,支持关键词匹配(描述、来源、级别、事件ID、类型名)。
2. 事件详情窗:双击事件行弹出,显示完整信息,并一键联网搜索(百度/必应/谷歌可配置)。
3. 复制功能增强:支持多选单元格复制、整行复制(修复1.4版本的“复制行”)(用制表符+“|”+制表符分隔,多行自动换行)。
4. 配置文件支持:首次运行自动生成 INI,可自定义事件ID描述和搜索引擎。
5. 内存安全修复:解决 EventRecord 对象内存泄漏,提升稳定性。
6. 更新一个图标:用AI画了一个图标,已经更新好了。

网络下载:https://wwbbo.lanzoub.com/b00wngftre 密码:baoi

本地下载:Windows系统日志查询工具v1.5.rar


主要功能

日期范围快速选择:支持“今天”、“昨天”、“前天”、“前一个月”、“前三个月”、“全部日期”等快捷按钮,也可手动选择起止日期。

事件类型筛选:可独立勾选 启动 / 关机 / 休眠/唤醒 / 错误 / 其他 五类事件,实时过滤显示。
结果表格展示:清晰展示时间、事件ID、级别、来源、类型、描述,不同类型自动着色区分。
右键菜单操作:复制单元格 / 复制行 / 清空记录 / 导出为 CSV,方便数据处理。
状态栏统计:实时显示总事件数和匹配数,以及查询耗时。
单击表头排序:支持按任意列排序(时间、ID、级别、来源、类型、描述),单击切换升序/降序。

为了彻底解决重复查询的卡顿问题,我设计了一套两层缓存机制:分层智能缓存2.0
基础层(按天缓存)
每次查询时,将读取到的原始事件按“天”拆分,分别存入内存(键为 yyyyMMdd)。
例如查询“前一个月”时,工具会一次性读取整个月的数据,然后自动按天存储。后续再查询其中某一天或某几天时,直接从缓存中组装,无需再次读取系统日志。

组合层(范围+筛选缓存)
对于用户查询过的完整日期范围+特定筛选条件(如“2025-01-01 至 2025-01-31 + 仅启动事件”),系统会将其结果单独缓存,并维护与基础缓存中每一天的依赖关系。
如果某一天的基础缓存因更新或淘汰而被清除,相关的组合缓存会自动失效,保证数据一致性。

得益于这种设计:
首次查询(例如“前一个月”)会从系统日志读取并缓存,耗时可能几秒到几十秒(取决于事件量)。
再次查询相同范围(或相同筛选条件)时,直接命中组合缓存,毫秒级返回。
跨范围查询(例如先查“今天”,再查“前一个月”)时,若“前一个月”的部分天数已缓存,则会从缓存中合并数据,大幅减少实际读取量。
此外,缓存还具备容量限制(最多 60 天原始数据 / 100 个组合缓存)和自动过期清理(1 小时未访问自动移除),避免内存膨胀。

因为事件描述都太长了。我只挑了几个缩短了一下描述,见下面的LogReader.cs

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Management;

using System.Diagnostics.Eventing.Reader;

using System.Security.Principal;

using System.Threading.Tasks;

 

namespace EventLogQueryTool

{

    public class LogReader

    {

        private bool _hasAdminPrivileges = false;

        private bool _privilegeChecked = false;

 

        private readonly Dictionary<int, (EventType, string)> _eventDescriptionMap = new Dictionary<int, (EventType, string)>

        {

            { 6005, (EventType.Startup, "系统已正常启动") },

            { 6006, (EventType.Shutdown, "系统已正常关机") },

            { 6008, (EventType.Shutdown, "系统上次未正常关机,可能是意外断电") },

            { 12, (EventType.Startup, "系统已启动,操作系统已加载完成") },

            { 41, (EventType.Error, "系统意外断电或重启") },

            { 1074, (EventType.Shutdown, "用户发起关机或重启操作") },

            { 1, (EventType.Hibernate, "系统从睡眠状态中唤醒") },

            { 42, (EventType.Hibernate, "系统进入睡眠状态") },

            { 506, (EventType.Hibernate, "系统从休眠状态恢复") },

            { 16, (EventType.Other, "IOMMU错误报告已初始化") },

            { 2, (EventType.Other, "Intel管理引擎接口驱动已启动") },

            { 6, (EventType.Other, "文件系统筛选器已成功加载") },

            { 98, (EventType.Other, "磁盘卷运行状况良好") },

            { 55, (EventType.Other, "处理器电源管理功能已配置") },

            { 125, (EventType.Other, "已枚举电源管理热区域") },

            { 172, (EventType.Other, "备用连接已断开") },

            { 20, (EventType.Other, "闰秒配置已更新") },

            { 14, (EventType.Other, "凭证保护已配置") },

            { 15, (EventType.Other, "凭证保护和虚拟化安全已配置") },

            { 6155, (EventType.Other, "凭证保护可能受影响,LSA包签名异常") },

            { 36871, (EventType.Other, "安全连接创建失败,可能影响网络通信") },

            { 4000, (EventType.Other, "无线网络自动配置服务已启动") },

            { 7000, (EventType.Error, "系统文件保护服务启动失败") },

            { 7001, (EventType.Error, "IP硬件服务启动失败") },

            { 1003, (EventType.Other, "系统搜索服务已启动") },

            { 900, (EventType.Other, "软件保护服务正在启动") },

            { 902, (EventType.Other, "软件保护服务已启动") },

            { 1000, (EventType.Error, "应用程序错误") },

            { 1001, (EventType.Other, "Windows错误报告") },

            { 1026, (EventType.Error, "应用程序异常终止") },

            { 1008, (EventType.Other, "性能数据将不可用") },

            { 153, (EventType.Other, "基于虚拟化的安全性已禁用") },

            { 18, (EventType.Other, "系统有多个启动选项") },

            { 19, (EventType.Other, "系统有多个引导工具选项") },

            { 17, (EventType.Other, "已显示多系统选择启动菜单") },

            { 32, (EventType.Other, "引导程序等待用户输入时间很短") },

            { 25, (EventType.Other, "引导菜单策略已设置") },

            { 27, (EventType.Other, "系统引导类型已确认") },

            { 30, (EventType.Other, "系统已报告启动指标") },

            { 24, (EventType.Other, "时区信息已更新") },

            { 7026, (EventType.Other, "部分引导启动驱动程序未加载") },

            { 11, (EventType.Other, "文件系统筛选器不支持绕过IO") }

        };

 

        private readonly string[] _logNames = new[]

        {

            "System",

            "Application",

            "Microsoft-Windows-Diagnostics-Performance/Operational"

        };

 

        public List<EventItem> ReadEvents(DateTime start, DateTime end)

        {

            Debug.WriteLine($"&#128197; 查询时间范围: {start:yyyy-MM-dd HH:mm:ss} 到 {end:yyyy-MM-dd HH:mm:ss}");

 

            bool hasAdminPrivileges = CheckAdminPrivileges();

            Debug.WriteLine($"开始读取事件日志,权限状态: 管理员 = {hasAdminPrivileges}");

 

            var availableLogs = GetAvailableLogNames().ToList();

            if (availableLogs.Count > 0)

            {

                if ((end - start).TotalDays > 7)

                {

                    Debug.WriteLine("时间范围较大,启用分块读取策略");

                    return ReadWithEventLogReaderInChunks(start, end, availableLogs);

                }

                else

                {

                    var result = ReadWithEventLogReader(start, end, availableLogs);

                    if (result.Count > 0) return result;

                }

            }

 

            try

            {

                var result = ReadWithEventLog(start, end);

                if (result.Count > 0) return result;

            }

            catch (Exception ex) { Debug.WriteLine($"EventLog 读取失败: {ex.Message}"); }

 

            try

            {

                var result = ReadWithWmi(start, end);

                if (result.Count > 0) return result;

            }

            catch (Exception ex) { Debug.WriteLine($"WMI 读取失败: {ex.Message}"); }

 

            Debug.WriteLine("所有读取策略均失败,返回空列表");

            return new List<EventItem>();

        }

 

        private List<EventItem> ReadWithEventLogReader(DateTime start, DateTime end, IEnumerable<string> logNames)

        {

            var allEvents = new List<EventItem>();

            var availableLogs = logNames.Where(IsLogAvailable).ToList();

            if (availableLogs.Count == 0) return allEvents;

 

            int maxParallelism = (end - start).TotalDays > 7 ? 2 : 4;

            Parallel.ForEach(availableLogs, new ParallelOptions { MaxDegreeOfParallelism = maxParallelism }, logName =>

            {

                var stopwatch = Stopwatch.StartNew();

                var events = SafeReadEventLog(logName, start, end);

                stopwatch.Stop();

                Debug.WriteLine($"日志 {logName}: {events.Count} 条记录,耗时 {stopwatch.ElapsedMilliseconds}ms");

 

                lock (allEvents) allEvents.AddRange(events);

            });

 

            return allEvents;

        }

 

        private List<EventItem> ReadWithEventLogReaderInChunks(DateTime start, DateTime end, IEnumerable<string> logNames)

        {

            var allEvents = new List<EventItem>();

            double totalDays = (end - start).TotalDays;

            TimeSpan chunkSize = totalDays > 30 ? TimeSpan.FromDays(5) :

                                 totalDays > 7 ? TimeSpan.FromDays(3) :

                                 TimeSpan.FromDays(1);

 

            Debug.WriteLine($"分块读取: 块大小 {chunkSize.Days} 天");

 

            foreach (var logName in logNames)

            {

                if (!IsLogAvailable(logName)) continue;

 

                var currentStart = start;

                while (currentStart < end)

                {

                    var currentEnd = currentStart + chunkSize;

                    if (currentEnd > end) currentEnd = end;

 

                    var chunkEvents = SafeReadEventLogChunk(logName, currentStart, currentEnd);

                    if (chunkEvents.Count > 0)

                        allEvents.AddRange(chunkEvents);

 

                    currentStart = currentEnd;

                    if (currentStart < end) System.Threading.Thread.Sleep(50);

                }

            }

 

            return allEvents;

        }

 

        private List<EventItem> ReadWithEventLog(DateTime start, DateTime end)

        {

            var events = new List<EventItem>();

            foreach (string logName in _logNames)

            {

                if (!EventLog.Exists(logName)) continue;

                try

                {

                    using (EventLog log = new EventLog(logName))

                    {

                        foreach (EventLogEntry entry in log.Entries)

                        {

                            if (entry.TimeGenerated >= start && entry.TimeGenerated <= end)

                            {

                                var item = ConvertEventLogEntry(entry);

                                if (item != null) events.Add(item);

                            }

                        }

                    }

                }

                catch (Exception ex) { Debug.WriteLine($"EventLog 读取 {logName} 失败: {ex.Message}"); }

            }

            return events;

        }

 

        private List<EventItem> ReadWithWmi(DateTime start, DateTime end)

        {

            var events = new List<EventItem>();

            try

            {

                string startWmi = ManagementDateTimeConverter.ToDmtfDateTime(start);

                string endWmi = ManagementDateTimeConverter.ToDmtfDateTime(end);

                string query = $"SELECT * FROM Win32_NTLogEvent WHERE TimeGenerated >= '{startWmi}' AND TimeGenerated <= '{endWmi}'";

 

                using (var searcher = new ManagementObjectSearcher(query))

                {

                    foreach (var obj in searcher.Get().Cast<ManagementObject>())

                    {

                        var item = ConvertManagementObject(obj);

                        if (item != null) events.Add(item);

                    }

                }

            }

            catch (Exception ex) { Debug.WriteLine($"WMI 查询失败: {ex.Message}"); }

            return events;

        }

 

        private EventItem ConvertEventRecord(EventRecord record)

        {

            try

            {

                int eventId = (int)record.Id;

                string source = record.ProviderName;

                string description = GetFriendlyDescription(eventId, source, record.FormatDescription());

                return new EventItem

                {

                    Time = record.TimeCreated?.ToLocalTime() ?? DateTime.MinValue,

                    EventId = eventId,

                    Level = record.LevelDisplayName,

                    Source = OptimizeSourceName(source),

                    Type = GetEventType(eventId, source),

                    Description = description

                };

            }

            catch { return null; }

        }

 

        private EventItem ConvertEventLogEntry(EventLogEntry entry)

        {

            try

            {

                int eventId = (int)entry.InstanceId;

                string source = entry.Source;

                string description = GetFriendlyDescription(eventId, source, entry.Message);

                return new EventItem

                {

                    Time = entry.TimeGenerated,

                    EventId = eventId,

                    Level = entry.EntryType.ToString(),

                    Source = OptimizeSourceName(source),

                    Type = GetEventType(eventId, source),

                    Description = description

                };

            }

            catch { return null; }

        }

 

        private EventItem ConvertManagementObject(ManagementObject obj)

        {

            try

            {

                int eventId = Convert.ToInt32(obj["EventCode"]);

                string source = obj["SourceName"]?.ToString() ?? "";

                string level = obj["Type"]?.ToString() ?? "";

                DateTime? time = ManagementDateTimeConverter.ToDateTime(obj["TimeGenerated"]?.ToString());

                string description = GetFriendlyDescription(eventId, source, obj["Message"]?.ToString() ?? "");

                return new EventItem

                {

                    Time = time ?? DateTime.MinValue,

                    EventId = eventId,

                    Level = level,

                    Source = OptimizeSourceName(source),

                    Type = GetEventType(eventId, source),

                    Description = description

                };

            }

            catch { return null; }

        }

 

        private EventType GetEventType(int eventId, string source)

        {

            if (_eventDescriptionMap.TryGetValue(eventId, out var tuple))

                return tuple.Item1;

 

            if (source.Contains("Power") || source.Contains("Power-Troubleshooter")) return EventType.Other;

            if (source.Contains("Security") || source.Contains("SPP")) return EventType.Other;

            if (source.Contains("Service") || source.Contains("Control Manager")) return EventType.Other;

            if (source.Contains("Winlogon") || source.Contains("User Profiles")) return EventType.Other;

            if (source.Contains("Startup") || source.Contains("Boot") || source.Contains("Kernel-Boot")) return EventType.Startup;

            if (source.Contains("Hardware") || source.Contains("Kernel") || source.Contains("Driver")) return EventType.Other;

            if (source.Contains("Shutdown") || source.Contains("Kernel-Power")) return EventType.Shutdown;

            if (source.Contains("Hibernate") || source.Contains("Sleep") || source.Contains("Resume")) return EventType.Hibernate;

            if (source.Contains("Error") || source.Contains("Critical") || source.Contains("Failure")) return EventType.Error;

 

            return EventType.Other;

        }

 

        private string GetFriendlyDescription(int eventId, string source, string description)

        {

            if (string.IsNullOrEmpty(description))

                return "无描述信息";

 

            if (_eventDescriptionMap.TryGetValue(eventId, out var tuple))

                return tuple.Item2;

 

            if (description.Contains("系统启动时间为") || description.Contains("system startup time is"))

            {

                var match = System.Text.RegularExpressions.Regex.Match(description, @"(\d+)\s*秒");

                if (match.Success && int.TryParse(match.Groups[1].Value, out int seconds))

                {

                    string timeDesc = $"系统启动完成,启动耗时: {seconds}秒";

                    if (seconds < 10) timeDesc += "(快速启动)";

                    else if (seconds < 20) timeDesc += "(正常启动)";

                    else timeDesc += "(较慢启动)";

                    return timeDesc;

                }

                return "系统启动完成";

            }

 

            return OptimizeEventDescription(description, eventId, source);

        }

 

        private string OptimizeEventDescription(string description, int _, string __)

        {

            if (string.IsNullOrEmpty(description)) return "无描述信息";

 

            description = description.Replace("Microsoft-Windows-", "")

                                     .Replace("EventLog", "事件日志")

                                     .Replace("Service Control Manager", "服务管理器")

                                     .Replace("The ", "")

                                     .Replace("Windows", "系统");

 

            if (description.Length > 100)

                description = description.Substring(0, 100) + "...";

 

            return description;

        }

 

        private string OptimizeSourceName(string source)

        {

            const int MAX_LEN = 30;

            if (string.IsNullOrEmpty(source)) return "未知来源";

 

            var mappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)

            {

                { "Microsoft-Windows-Kernel-Power", "电源管理" },

                { "Microsoft-Windows-Kernel-Boot", "系统启动" },

                { "Microsoft-Windows-Power-Troubleshooter", "电源问题" },

                { "Service Control Manager", "服务管理器" },

                { "EventLog", "事件日志" },

                { "Microsoft-Windows-Diagnostics-Performance", "性能诊断" },

                { "Microsoft-Windows-Winlogon", "用户登录" },

                { "Microsoft-Windows-Security-SPP", "软件保护" },

                { "Microsoft-Windows-FilterManager", "文件系统" },

                { "Microsoft-Windows-Ntfs", "NTFS文件系统" },

                { "Microsoft-Windows-WLAN-AutoConfig", "无线网络" },

                { "Microsoft-Windows-Schannel", "安全连接" }

            };

 

            foreach (var m in mappings)

                if (source.Contains(m.Key))

                    return m.Value;

 

            if (source.StartsWith("Microsoft-Windows-"))

            {

                string keyPart = source.Substring("Microsoft-Windows-".Length);

                int slash = keyPart.IndexOf('/');

                if (slash > 0) keyPart = keyPart.Substring(0, slash);

                keyPart = keyPart.Replace("-", " ");

                if (keyPart.Length > MAX_LEN)

                {

                    var parts = keyPart.Split(' ');

                    keyPart = parts.Length > 1 ? parts[parts.Length - 1] : keyPart;

                    if (keyPart.Length > MAX_LEN) keyPart = keyPart.Substring(0, MAX_LEN) + "...";

                }

                return keyPart;

            }

 

            return source.Length > MAX_LEN ? source.Substring(0, MAX_LEN) + "..." : source;

        }

 

        private bool CheckAdminPrivileges()

        {

            if (_privilegeChecked) return _hasAdminPrivileges;

            try

            {

                WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());

                _hasAdminPrivileges = principal.IsInRole(WindowsBuiltInRole.Administrator);

            }

            catch { _hasAdminPrivileges = false; }

            _privilegeChecked = true;

            return _hasAdminPrivileges;

        }

 

        public string GetPrivilegeWarningMessage()

        {

            return CheckAdminPrivileges() ?

                "当前具有管理员权限,可以读取所有事件日志。" :

                "当前权限不足,只能读取部分事件日志。建议以管理员身份运行程序以获得完整功能。";

        }

 

        private bool IsLogAvailable(string logName)

        {

            var known = new[] { "System", "Application", "Microsoft-Windows-Diagnostics-Performance/Operational" };

            if (known.Contains(logName, StringComparer.OrdinalIgnoreCase)) return true;

            try { return EventLog.Exists(logName); }

            catch { return false; }

        }

 

        private List<EventItem> SafeReadEventLog(string logName, DateTime start, DateTime end)

        {

            if (end - start > TimeSpan.FromDays(7))

                return ReadEventLogInChunks(logName, start, end);

 

            var events = new List<EventItem>();

            string query = $"*[System[TimeCreated[@SystemTime >= '{start.ToUniversalTime():o}' and @SystemTime <= '{end.ToUniversalTime():o}']]]";

            try

            {

                using (var reader = new EventLogReader(new EventLogQuery(logName, PathType.LogName, query)))

                {

                    EventRecord record;

                    while ((record = reader.ReadEvent()) != null)

                    {

                        var item = ConvertEventRecord(record);

                        if (item != null) events.Add(item);

                    }

                }

            }

            catch (Exception ex) { Debug.WriteLine($"SafeReadEventLog 错误: {ex.Message}"); }

            return events;

        }

 

        private List<EventItem> ReadEventLogInChunks(string logName, DateTime start, DateTime end)

        {

            var all = new List<EventItem>();

            double days = (end - start).TotalDays;

            TimeSpan chunk = days > 30 ? TimeSpan.FromDays(5) : days > 7 ? TimeSpan.FromDays(3) : TimeSpan.FromDays(1);

            var current = start;

            while (current < end)

            {

                var chunkEnd = current + chunk;

                if (chunkEnd > end) chunkEnd = end;

                var chunkEvents = SafeReadEventLogChunk(logName, current, chunkEnd);

                if (chunkEvents.Count > 0) all.AddRange(chunkEvents);

                current = chunkEnd;

                if (current < end) System.Threading.Thread.Sleep(50);

            }

            return all;

        }

 

        private List<EventItem> SafeReadEventLogChunk(string logName, DateTime start, DateTime end)

        {

            var events = new List<EventItem>();

            string query = $"*[System[TimeCreated[@SystemTime >= '{start.ToUniversalTime():o}' and @SystemTime <= '{end.ToUniversalTime():o}']]]";

            try

            {

                using (var reader = new EventLogReader(new EventLogQuery(logName, PathType.LogName, query)))

                {

                    EventRecord record;

                    int count = 0;

                    while ((record = reader.ReadEvent()) != null && count < 10000)

                    {

                        var item = ConvertEventRecord(record);

                        if (item != null) { events.Add(item); count++; }

                    }

                }

            }

            catch { /* 静默失败 */ }

            return events;

        }

 

        private IEnumerable<string> GetAvailableLogNames()

        {

            foreach (var name in _logNames)

                if (IsLogAvailable(name))

                    yield return name;

        }

    }

}


该文章在 2026/4/3 17:13:06 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved