使用GetFileSizeEx获取Windows系统日志文件大小传入错误句柄问题求助
正确获取EVTX日志文件大小的方法
你遇到的问题核心在于:GetFileSizeEx需要的是文件系统句柄,而你传入的EvtQuery、EvtGetChannelConfigProperty、OpenEventLog返回的都是Windows事件日志子系统的内部句柄,这两类句柄完全不兼容。
为什么之前的句柄不行?
EvtQuery和EvtGetChannelConfigProperty返回的是事件日志查询/配置句柄,用于和Windows Event Log服务交互,不是直接指向磁盘上的文件;OpenEventLog返回的是事件日志会话句柄,同样是用于系统事件日志的操作,不是文件系统层面的句柄。
这些句柄只能在对应的Event Log API中使用,无法被GetFileSizeEx这类文件系统API识别,所以才会出现「传入错误句柄」的错误。
正确的实现步骤
要获取%SystemRoot%\System32\winevt\logs下EVTX文件的大小,你需要直接操作磁盘上的文件,步骤如下:
- 拼接完整的文件路径(利用
GetEnvironmentVariable获取SystemRoot环境变量); - 使用
CreateFile打开目标EVTX文件(注意设置正确的共享模式,因为系统可能正在占用该文件); - 调用
GetFileSizeEx获取文件大小; - 关闭文件句柄并处理可能的错误。
示例代码
#include <windows.h> #include <iostream> #include <string> int main() { // 获取SystemRoot环境变量 wchar_t systemRoot[MAX_PATH]; if (!GetEnvironmentVariableW(L"SystemRoot", systemRoot, MAX_PATH)) { std::cerr << "获取SystemRoot失败,错误码: " << GetLastError() << std::endl; return 1; } // 拼接目标文件路径,比如Application.evtx std::wstring filePath = std::wstring(systemRoot) + L"\\System32\\winevt\\logs\\Application.evtx"; // 打开文件:需要指定共享模式,因为系统可能正在读写该日志文件 HANDLE hFile = CreateFileW( filePath.c_str(), GENERIC_READ, // 只需要读权限 FILE_SHARE_READ | FILE_SHARE_WRITE, // 允许其他进程读写 nullptr, OPEN_EXISTING, // 打开已存在的文件 FILE_ATTRIBUTE_NORMAL, nullptr ); if (hFile == INVALID_HANDLE_VALUE) { std::cerr << "打开文件失败,错误码: " << GetLastError() << std::endl; return 1; } // 获取文件大小 LARGE_INTEGER fileSize; if (!GetFileSizeEx(hFile, &fileSize)) { std::cerr << "获取文件大小失败,错误码: " << GetLastError() << std::endl; CloseHandle(hFile); return 1; } // 输出结果:可以转换为字节、KB、MB等 std::cout << "文件大小(字节): " << fileSize.QuadPart << std::endl; std::cout << "文件大小(MB): " << static_cast<double>(fileSize.QuadPart) / (1024 * 1024) << std::endl; // 关闭句柄 CloseHandle(hFile); return 0; }
额外提示
如果不想硬编码日志文件名,可以先用EvtGetChannelConfigProperty传入EvtChannelConfigLogFilePath参数,获取对应事件通道的实际日志文件路径,再用上述方法打开文件获取大小,这样能更灵活地适配不同的日志通道。
内容的提问来源于stack exchange,提问作者Nash
相关产品推荐
相关产品推荐

