讲师中心 微信公众号
AI工具推荐 视频效率加速

c++如何读取和解析Windows事件日志(.evtx)的二进制块【深度】

老敏小哥_3999

老敏小哥_3999

发布时间:2026-04-13 20:27:18

|

791人浏览过

|

来源于php中文网

原创

Windows事件日志(.evtx)需用EvtQuery+FilePath标志离线解析或libevtx库,不可直接fread;EvtRender需动态缓冲区获取XML,跨平台首选libevtx但须谨慎封装。

c++如何读取和解析windows事件日志(.evtx)的二进制块【深度】

Windows事件日志(.evtx)不是普通二进制文件,不能用fread直接解析

EVTX 文件是基于 XML 的二进制序列化格式(ETW 二进制编码),底层使用 Windows 自有的 EvtxFormat 结构,包含头部块、记录块、字符串表、模板缓存等。直接用 C++ 的 std::ifstream 读取 raw bytes 后试图“手动解码”会立刻卡在块对齐、压缩字段、GUID 解析、时间戳反向编码(FILETIME → 100ns intervals)、XML 模板实例化等环节——这不是字节流解析,而是逆向整个 Windows 日志运行时序列化协议。

真正可行的路径只有两条:

  • 调用 Windows 原生 API:EvtQuery / EvtNext / EvtRender,这是微软唯一保证兼容的方式
  • 复用成熟开源解析器(如 python-evtx 的 C++ 移植版或 libevtx),但需注意其维护状态和 Windows 特性支持程度(例如不支持 Vista 之前旧格式、无 WPP 日志扩展字段)

用EvtQuery + EvtNext 读取本地 .evtx 文件必须指定EvtQueryFilePath标志

很多人误以为 EvtQuery 只能查实时日志(如 Security、System),其实它也支持离线 EVTX 文件,但关键在于查询句柄创建时的标志位。若漏掉 EvtQueryFilePath,API 会静默失败并返回 NULL 句柄,后续 EvtNext 调用直接崩溃或返回 ERROR_INVALID_PARAMETER。

正确写法示例(简化错误检查):

立即学习“C++免费学习笔记(深入)”;

EVT_HANDLE hQuery = EvtQuery(
    NULL,
    L"C:\path\to\log.evtx",  // 注意:必须是宽字符路径
    L"*",                      // XPath 查询,* 表示全部事件
    EvtQueryFilePath          // ⚠️ 必须显式传入!不能省略或用 0 替代
);
if (!hQuery) {
    DWORD err = GetLastError(); // 常见:ERROR_FILE_NOT_FOUND 或 ERROR_ACCESS_DENIED
}

其他易错点:

windows-git-ops
windows-git-ops

在 Windows PowerShell 工作区执行 Git 操作时使用此技能,特别适用于创建分支、暂存、提交、合并、状态检查等。

下载
  • 路径必须为绝对路径且使用 L"" 宽字符串;相对路径、ANSI 字符串均失败
  • 文件需有读取权限(尤其系统生成的 EVTX 常带 DACL 限制,普通用户可能被拒绝)
  • 不能在 32 位程序中读取由 64 位 Windows 写入的 EVTX(因某些结构体字段对齐差异,EvtRender 渲染时会出错)

EvtRender 输出 XML 需指定EvtRenderEventXml且缓冲区要动态重试

EVTTX 中单条事件的 XML 渲染结果长度不固定,且可能含嵌入二进制数据(如 EventData 下的 Binary 元素)。直接传一个固定大小缓冲区(如 4KB)大概率触发 ERROR_INSUFFICIENT_BUFFER,此时必须用返回的 dwBufferSize 值重新分配内存再调用。

典型流程:

DWORD dwSize = 0;
DWORD dwReturned = 0;
EvtRender(NULL, hEvent, EvtRenderEventXml, 0, NULL, &dwSize, &dwReturned); // 第一次试探
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    std::vector<char> buf(dwSize);
    if (EvtRender(NULL, hEvent, EvtRenderEventXml, dwSize, buf.data(), &dwSize, &dwReturned)) {
        std::string xml(buf.begin(), buf.begin() + dwReturned);
        // 解析 xml 字符串(可用 tinyxml2、pugixml 等)
    }
}

注意:

  • EvtRenderEventXml 输出的是完整 XML(含 <Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>),不是纯文本摘要
  • 若只需部分字段(如 TimeCreated、Level),改用 EvtRenderEventValues + EvtVarType 枚举更高效,避免 XML 解析开销
  • 渲染失败常见原因是事件中含损坏模板或缺失注册表中的 Provider 元数据(此时 EvtRender 返回 FALSE,GetLastError() 为 ERROR_EVT_CHANNEL_NOT_FOUND)

跨平台或免 Windows API 依赖?libevtx 是唯一较稳的选择,但别碰它的 C++ 封装

GitHub 上的 libevtx(由 libyal 维护)是目前最完整的开源 EVTX 解析库,纯 C 实现,支持所有 Windows 版本的 EVTX 格式(包括 Win7 的压缩块、Win10 的增量更新块)。但它没有官方 C++ 接口,强行封装容易踩坑:

  • C++ RAII 包装器若未正确处理 libevtx_file_t* 的生命周期,会导致多次 libevtx_file_free 崩溃
  • 其错误码体系是负值(如 -1 表示失败),与 Windows API 的 BOOL 习惯相反,混用极易逻辑翻转
  • 字符串字段(如 libevtx_event_get_record_number)返回的是内部指针,生命周期绑定于 file handle,不可长期持有

建议做法:用 C 风格直调,只做最小胶水层:

libevtx_file_t *file = NULL;
if (libevtx_file_initialize(&file, &error) != 1) { /* 失败 */ }
if (libevtx_file_open_file_io_handle(file, file_io_handle, &error) != 1) { /* 失败 */ }
libevtx_event_t *event = NULL;
if (libevtx_file_get_event_by_index(file, 0, &event, &error) == 1) {
    uint64_t record_number = 0;
    libevtx_event_get_record_number(event, &record_number, &error);
    // ... 使用 record_number
}
libevtx_event_free(&event); // 必须显式 free

真正难的从来不是读取字节,而是理解 Windows 如何把事件对象序列化成块链表、如何用模板缓存复用 XML 结构、以及为什么一条事件的 RenderingInfo 可能引用远程注册表项——这些细节决定了你写的代码是能跑通一个 demo,还是能在生产环境稳定解析三年的日志归档。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1678

2024.03.01

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

4404

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

5697

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2402

2024.11.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1678

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2564

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

5984

2023.10.24

PixTV官网入口地址合集
PixTV官网入口地址合集

本专题汇总了 PixTV AI 一站式视频创作平台的官方入口与使用教程。无需下载软件,浏览器直接访问即可使用。平台将剧本、图像、视频、声音与剪辑整合在“无限画布”中,接入 GPT Image 2.5、Seedance 2.5 等头部模型。本专题整理了从新建画布、角色锚定、分镜拆分到视频生成与导出的完整操作指南,助你快速上手 AI 短剧与漫剧创作。

80

2026.10.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Conan 2 安装指南
Conan 2 安装指南

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn