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($"📅 查询时间范围: {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;
}
}
}