获取Windows日志的常规下的描述(c/c++)

请问怎么获取Windows日志的常规内容,不是详细xml的那个内容

img

方法教你,代码自己写吧
参考示例 https://learn.microsoft.com/en-us/windows/win32/eventlog/receiving-event-notification

1. 获取到 EVENTLOGRECORD  
2. 获取到EventSource, TCHAR* source = (TCHAR*)((BYTE*)eventrecord + sizeof(EVENTLOGRECORD))
3. 注册表读取 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/EventLog/System/<EventSource名称>/EventMessageFile
4. 加载得到的多个DLL,LoadLibraryEx(dll名称, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE)
5. FormatMessage传入DLL的handle,得到中间字符串,参考示例中的GetMessageString函数和调用它的地方
6. 中间字符串中的所有 %XXX,再调用FormatMessage得到字符串,替换掉。参考示例中的ApplyParameterStringsToMessage函数
7. 打印输出结果字符串
8. 卸载DLL

这是我的代码,就是把Windows日志改为syslog形式,但是现在缺少一个message内容,想获取那个内容描述不知道怎么获取啊


这是我的代码,就是把Windows日志转成syslog格式的内容进行打印,但是现在缺少一个内容,xml的那个不能作为内容啊
#include <windows.h>
#include <iostream>
#include <string>
//std::wstring wstrMessage((wchar_t*)((BYTE*)pEventLogRecord + pEventLogRecord->StringOffset))
using namespace std;
#define set_char 20000
int main()
{
    LPVOID lpMsgBuf;
    int set_num2 = 0;
    DWORD dwRead, dwNeeded, dwThisRecord;
    string Source;
    time_t Time;
    unsigned short ID;
    EVENTLOGRECORD* pevlr;
    char *Data = new char[set_char]; //缓冲区大小,如果太小读到的记录会少于windows日志
    HANDLE Log = OpenEventLog(NULL, "System");//第一次参数表示本地计算机,第二个参数表示系统日志
    if (Log == NULL)
    {
        cout << "==" << endl;
        return 0;
    }
    GetOldestEventLogRecord(Log, &dwThisRecord);
    int a = 0;

    while (true)
    {
        if (a = ReadEventLog(Log, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, Data, set_char, &dwRead, &dwNeeded))
        {

            for (DWORD i = 0; i < dwRead;)
            {
                EVENTLOGRECORD* ptr = (EVENTLOGRECORD*)(Data + i);
                Source = (TCHAR*)ptr + sizeof(EVENTLOGRECORD);//事件源
                ID = (unsigned short)ptr->EventID;//事件ID
                //&& Source != "EventLog"
                /*if (Source != "Microsoft-Windows-Kernel-General")
                {
                    i += ptr->Length;
                    continue;
                }*/
                struct tm SysStartupTime;//时间结构体
                Time = ptr->TimeGenerated;//日期和时间
                char buf[64]{ 0 };//用来存放时间
                localtime_s(&SysStartupTime, &Time);//时间戳转化为格式时间
                strftime(buf, _countof(buf), "%Y-%m-%d %H:%M:%S", &SysStartupTime);//格式化时间到缓冲区
                char* pchar = (TCHAR*)ptr + sizeof(EVENTLOGRECORD);
                pchar += (strlen(pchar) + 1);
                string UserID = pchar;
                string User;
                pchar += strlen(pchar) + 1;
                char Buffer[1024];

                if (ptr->UserSidLength > 0)
                {
                    char Name[64];
                    DWORD Length = sizeof(SID), Length1 = sizeof(Buffer);
                    SID_NAME_USE Type = SidTypeUser;
                    SID* sid = (SID*)(Data + ptr->UserSidOffset);
                    if (LookupAccountSid(NULL, sid, Name, &Length, Buffer, &Length1, &Type))
                        User = Name;
                }
                //cout << "---------------系统--------------" << endl;
                //cout << "事件:";
                string Type;
                switch (ptr->EventType)
                {
                case 0: Type = "2"; break;
                case 1: Type = "3"; break;
                case 2: Type = "4"; break;
                case 4: Type = "5"; break;
                default:continue;
                }
                string str;
                str += "<";
                str += Type;
                str += ">";
                //    str += "Time:";
                str += buf;
                str += " ";
                //    str += " Hostname:";
                str += UserID;
                str += " ";
                //    str += " APPNANME:";
                str += (char*)(LPBYTE)ptr + sizeof(EVENTLOGRECORD);
                str += ": ";
                //    str += " ID:";
                str += to_string(ID);
                str += " ";
                //    str += pchar;

                if (ptr->DataOffset > ptr->StringOffset)
                {
                    pchar = Data + i + ptr->StringOffset;

                    //printf("%s \n", pchar);
                    str += pchar;
                    for (short j = 0; j < ptr->NumStrings; j++)
                    {
                        pchar += strlen(pchar) + 1;
                        //cout << pchar << endl;
                        str += " ";
                        str += pchar;
                    }
                }
                if (ptr->NumStrings > 0)
                {
                    for (WORD j = 0; j < ptr->NumStrings; j++)
                    {
                        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                            NULL, *((LPDWORD)((LPBYTE)ptr + ptr->StringOffset + sizeof(DWORD) * j)), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL))
                        {
                            printf("Description: %s\n", (LPSTR)lpMsgBuf);
                            LocalFree(lpMsgBuf);
                        }
                    }
                }
                cout << str << endl;

                //cout << "----------" << str << "-----------" << endl;

                i += ptr->Length;
                //cout << endl;
            }
        }
    }
    delete[] Data;
    CloseEventLog(Log);
}

参考如下代码:


#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
int execmd(char* cmd, char* result) {
    char buffer[128];                         // 缓冲区                        
    FILE* pipe = _popen(cmd, "r");            // 管道 
    
    // 管道打开失败
    if (!pipe){return 0;}
 
    // 检测管道中的结束符,0表示没有结束
    while(!feof(pipe)){
        // 从管道中读取数据
        if (fgets(buffer, 128, pipe)) {             
            // 拼接 char
            strcat(result, buffer);
        }
    }
 
    //关闭管道 
    _pclose(pipe);           
 
    return 1;                                 
}
 
int main()
{
    char result[0x7ffff] = "";        // 存放结果
    
    // 获取命令行返回值(保险起见这里获取 300 条日志信息)
    if (execmd("wevtutil qe System /c:300 /rd:true /f:text", result) == 1) {
        cout << result << endl;
    }
 
    // 查找关键数据
    string s = result;
    while ((s.find("igfx")) != -1) {
        cout << "找到了 igfx " << endl;
        break;
    }
 
    system("pause");   
    return 0;
}

以下答案由GPT-4.0Plus大模型与博主A努力中.......共同编写:
在Windows系统中,有两种方式可以获取日志内容:

  1. 事件查看器(Event Viewer):这是Windows自带的日志查看工具,可以方便地浏览系统日志和应用程序日志。它显示的日志内容是较为简洁的,不包含XML标签等信息,比较符合“常规内容”的要求。
    可以在Windows搜索栏搜索“事件查看器”启动它,然后在左侧导航栏选择“Windows日志”和“应用程序”等目录,就可以查看相应的日志内容。
  2. Wevtutil命令:这是Windows的命令行日志工具,可以通过命令行获取日志内容。相比事件查看器,它可以通过命令行实现自动化日志查询等操作。
    要获取简洁的日志内容,可以使用如下Wevtutil命令:
    cmd
    wevtutil qe System /q:*[System[(Level=1 or Level=2)]] /c:10 /rd:true /f:text
    这个命令的意思是:
    查询System日志目录(即Windows系统日志)
    条件是日志级别为Warning或Error(Level=1或2)
    返回最近10条日志条目
    以文本格式返回(不包含XML标签)
    重新格式化输出以提高可读性(rd:true)
    执行该命令后,就可以在命令行窗口得到简洁的Windows系统日志内容。

除此之外,Windows还提供了logman和PowerShell等日志管理工具,也可以用于查询和订阅Windows日志。但相比事件查看器和Wevtutil,它们的日志输出格式可能更为复杂,不太适合您要的“常规内容”。

原生方案,我这里也没测试ok,也许你可以去看看托管C++的封装。

方案1、Wevtutil.exe
https://www.cnblogs.com/LyShark/p/15019941.html

#include "stdafx.h"
#include <iostream>

using namespace std;

int execmd(char* cmd, char* result) {
    char buffer[128];                         // 缓冲区                        
    FILE* pipe = _popen(cmd, "r");            // 管道 
    
    // 管道打开失败
    if (!pipe){return 0;}

    // 检测管道中的结束符,0表示没有结束
    while(!feof(pipe)){
        // 从管道中读取数据
        if (fgets(buffer, 128, pipe)) {             
            // 拼接 char
            strcat(result, buffer);
        }
    }

    //关闭管道 
    _pclose(pipe);           

    return 1;                                 
}

int main()
{
    char result[0x7ffff] = "";        // 存放结果
    
    // 获取命令行返回值(保险起见这里获取 300 条日志信息)
    if (execmd("wevtutil qe System /c:300 /rd:true /f:text", result) == 1) {
        cout << result << endl;
    }

    // 查找关键数据
    string s = result;
    while ((s.find("igfx")) != -1) {
        cout << "找到了 igfx " << endl;
        break;
    }

    system("pause");   
    return 0;
}


方案2、用托管C++项目(反正都是windows跑),用封装好的EventLog

    EventLog^ log = gcnew EventLog();
    log->Log = ("system");
    EventLogEntryCollection^ myCollection = log->Entries;
 
    for each (EventLogEntry^ test in myCollection)
    {
        Console::WriteLine(test->Message);
        Console::WriteLine(test->TimeWritten);
 
    }

具体步骤如下:
1.打开“事件查看器”(Event Viewer)。
2.在左侧窗格中选择“Windows日志”(Windows Logs)。
3.选择你想要查看的日志类型,如“应用程序”(Application)、“系统”(System)等。
4.在右侧窗格中,你将看到日志的列表。每个日志条目都包含时间戳、事件ID、级别、来源、描述等信息。
5.点击任意一条日志条目,你将看到该事件的详细信息,包括时间、级别、源、任务类别、关键字等。
6.如果你想导出日志内容,可以右键点击日志列表中的任意一个条目,选择“保存所有事件”(Save All Events),并选择要保存的文件格式和位置。
如有帮助,望采纳,谢谢!