如何在C#程序中连接Windows特定嵌套事件日志?
问题原因
你用的EventLog类是.NET旧版事件日志API,只能读取传统系统日志(比如Security、Application),根本访问不了Applications & Services分类下的现代Windows事件日志——像Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational这类嵌套日志,必须用System.Diagnostics.Eventing.Reader命名空间下的EventLogQuery、EventLogReader这类新API才能读取。
解决步骤
1. 替换日志读取逻辑
删掉原代码里EventLog eventLog = new EventLog(logChoice, comp);及后续的遍历代码,换成下面的实现:
// 构建查询规则:指定要过滤的事件ID string query = $"*[System/EventID={eventChoice}]"; EventLogQuery eventLogQuery = new EventLogQuery( logChoice, PathType.LogName, query); // 用EventLogReader读取日志 using (EventLogReader reader = new EventLogReader(eventLogQuery)) { EventRecord entry; while ((entry = reader.ReadEvent()) != null) { // 获取事件生成时间 DateTime time = entry.TimeCreated.Value; // 格式化事件消息(新API需要调用FormatDescription获取完整消息) string message = entry.FormatDescription(); // 复用你已经写好的IP、账号、域名提取方法 string ip = GetIP(message); string acc = GetAcc(message); string domain = GetDomain(message); // 格式化CSV行,避免时间格式导致的CSV错乱 string csvOutput = $"{time:yyyy-MM-dd HH:mm:ss},{ip},{acc},{domain}"; Console.WriteLine(csvOutput); csv.AppendLine(csvOutput); } }
2. 日志名称不用改
你用的Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational是完全正确的日志路径,不需要做任何修改。
3. 必须管理员权限
读取这类嵌套日志需要管理员权限,记得右键程序选择“以管理员身份运行”。
4. 补充异常捕获
新增针对日志不存在的异常捕获,方便排查问题:
catch (EventLogNotFoundException ex) { MessageBox.Show($"找不到指定日志:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); }
完整修改后的CheckEventLog函数
整合后的代码保留了你原有的导出逻辑,替换了核心的日志读取部分:
private void CheckEventLog() { if (exportPath == null || string.IsNullOrEmpty(exportPath.Text)) { MessageBox.Show("请输入导出路径。", "导出错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 处理计算机名称(保留你原有的本地逻辑,远程功能可后续恢复) comp = System.Environment.MachineName; if (!string.IsNullOrEmpty(compInput.Text)) { // 若要恢复远程读取,在这里补全用户名密码逻辑即可 // comp = compInput.Text; // username = usrImp.Text; // ... 密码转SecureString的代码 } string filePath = exportPath.Text; string csvHeader = "Date/Time,IP Address,Account Name,Account Domain"; var csv = new StringBuilder(); csv.AppendLine(csvHeader); try { // 现代事件日志查询逻辑 string query = $"*[System/EventID={eventChoice}]"; EventLogQuery eventLogQuery = new EventLogQuery( logChoice, PathType.LogName, query); using (EventLogReader reader = new EventLogReader(eventLogQuery)) { EventRecord entry; while ((entry = reader.ReadEvent()) != null) { DateTime time = entry.TimeCreated.Value; string message = entry.FormatDescription(); string ip = GetIP(message); string acc = GetAcc(message); string domain = GetDomain(message); string csvOutput = $"{time:yyyy-MM-dd HH:mm:ss},{ip},{acc},{domain}"; csv.AppendLine(csvOutput); } } File.WriteAllText(filePath, csv.ToString()); csvOUT = csv.ToString(); MessageBox.Show("导出完成!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (IOException ex) { MessageBox.Show($"文件操作错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (InvalidOperationException ex) { MessageBox.Show($"操作异常:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (EventLogNotFoundException ex) { MessageBox.Show($"日志不存在:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (Exception ex) { MessageBox.Show($"未知错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
额外提示
- 如果要恢复远程读取其他计算机的日志,需要用
EventLogSession初始化EventLogReader:
// 远程连接示例 EventLogSession session = new EventLogSession( comp, username, domain, securePassword, SessionAuthentication.Default); using (EventLogReader reader = new EventLogReader(eventLogQuery, session)) { // 读取逻辑和上面一致 }
- 事件ID 1149的消息格式和4625不一样,要检查你的正则表达式能不能正确提取对应字段。
内容的提问来源于stack exchange,提问作者TWB503
相关产品推荐
相关产品推荐

