想请问怎么持续获取最新的Windows日志内容,用c或者c++代码,或者帮我修改一下我的代码

//代码是想持续只读取最新的Windows日志内容,并转成syslog形式进行发送,但是不知道怎么获取message部分的内容,而且我的代码有一个问题,就是获取缓冲区的数据的时候,应该要从最新的地方读取才对,但是我不知道怎么从最新的地方读取,并且如果程序一直运行的话,缓冲区空间总会为空的
int main()
    int set_num3 = 0;
    DWORD dwRead, dwNeeded, dwThisRecord, dwRecordCount, dwRecordNumber;
    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;
                }
                if (set_num3 == 1)
                {
                    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;
                        }
                    }
                    cout << str << endl;
                }
                //cout << "----------" << str << "-----------" << endl;

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

别用al。al我都试了一周了,给不出答案的,而且al给的代码就有问题

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>

#define call(exp) if(exp){}else{ printf("%s fail, GetLastError=%d\n", #exp, (int)GetLastError()); exit(1); }

#define BUFFER_SIZE 0x7ffff
static BYTE buf_[BUFFER_SIZE];

//打印事件信息,这个你自己改一下
static void PrintEventRecord(EVENTLOGRECORD* record){    
    TCHAR* source = (TCHAR*)((BYTE*)record + sizeof(EVENTLOGRECORD));    
    printf("new event id: %d ",(int)record->EventID);    
    printf(" source: ");
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), source, lstrlen(source), NULL, NULL);   
    printf("\n");    
}

int _tmain(){
    DWORD count, lastnum, firstnum, readed, needed;    
    HANDLE event, log;
    EVENTLOGRECORD* record;
    BYTE* ptr;
    call((event = CreateEvent(NULL,FALSE,FALSE,NULL)) != NULL);
    call((log = OpenEventLog(NULL, TEXT("System"))) != NULL);    
    //定位到最新的log
    call(GetNumberOfEventLogRecords(log, &count));
    call(GetOldestEventLogRecord(log, &firstnum));
    lastnum = firstnum + count - 1;    
    call(ReadEventLog(log, EVENTLOG_SEEK_READ|EVENTLOG_FORWARDS_READ, lastnum, buf_, BUFFER_SIZE, &readed, &needed));
    //关联到event对象,有新log时触发event对象
    call(NotifyChangeEventLog(log, event));
    while(1){
        if(ReadEventLog(log, EVENTLOG_SEQUENTIAL_READ|EVENTLOG_FORWARDS_READ, 0, buf_, BUFFER_SIZE, &readed, &needed)){   
            //读到log时打印
            ptr = buf_;
            while(readed >= sizeof(EVENTLOGRECORD)){
                record = (EVENTLOGRECORD*)ptr;
                PrintEventRecord(record);
                ptr += record->Length;
                readed -= record->Length;
            }
        }else{
            //没有log时等待event触发
            WaitForSingleObject(event, INFINITE);
        }        
    }        
    return 0;
}
为了持续获取最新的Windows日志内容,你可以使用 ReadEventLog 函数来进行轮询。但是,你需要注意一些细节问题,例如:

从最新的地方读取:你可以使用 GetOldestEventLogRecord 函数来获取当前最新的记录号,然后在每次读取日志时,指定 EVENTLOG_SEEK_READ 标志和最新的记录号,这样就可以从最新位置开始读取日志。

缓冲区空间问题:你需要保证缓冲区的空间足够大,以容纳最新的日志记录。如果你的缓冲区过小,读取到的记录会少于Windows日志。在你的代码中,你已经定义了一个 Data 缓冲区大小为 set_char,因此你需要根据你的实际需求调整 set_char 的大小,确保缓冲区足够大。

获取 message 部分内容:在你的代码中,你已经使用 TCHAR* 类型指针来获取事件源和 message 部分的内容,这是正确的方法。在读取 EVENTLOGRECORD 结构体后,可以使用指针运算 sizeof(EVENTLOGRECORD) 来跳过事件头部,然后就可以使用 TCHAR* 类型指针来获取事件源和 message 部分的内容了。

下面是修改后的代码,可以持续获取最新的 Windows 日志内容并转换为 syslog 形式发送。

c
Copy
#include <Windows.h>
#include <iostream>
#include <string>
#include <ctime>
#pragma comment(lib, "advapi32.lib")

using namespace std;

int main()
{
    DWORD dwRead, dwNeeded, dwThisRecord, dwRecordCount, dwRecordNumber;
    string Source;
    time_t Time;
    unsigned short ID;
    EVENTLOGRECORD* pevlr;
    char* Data = new char[1024 * 1024]; // 缓冲区大小为 1MB
    HANDLE Log = OpenEventLog(NULL, "System"); // 打开系统日志
    if (Log == NULL)
    {
        cout << "Failed to open event log." << endl;
        return 0;
    }

    // 获取当前最新的记录号
    GetOldestEventLogRecord(Log, &dwThisRecord);

    while (true)
    {
        // 从最新位置开始读取日志
        dwRecordNumber = dwThis is the continuation of the previous answer.

ebnf
Copy
        if (!ReadEventLog(Log, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_SEEK_READ, dwThisRecord, Data, 1024*1024, &dwRead, &dwNeeded))
        {
            cout << "Failed to read event log." << endl;
            break;
        }

        // 更新当前最新的记录号
        dwThisRecord += dwRead / sizeof(EVENTLOGRECORD);

        for (DWORD i = 0; i < dwRead;)
        {
            EVENTLOGRECORD* ptr = (EVENTLOGRECORD*)(Data + i);
            Source = (TCHAR*)ptr + sizeof(EVENTLOGRECORD);// 事件源
            ID = (unsigned short)ptr->EventID;// 事件ID

            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);// 格式化时间到缓冲区

            // 获取 message 部分的内容
            char* pchar = (TCHAR*)ptr + sizeof(EVENTLOGRECORD) + ptr->StringOffset;

            string message(pchar);

            // 将日志转换为 syslog 格式
            string syslog;
            syslog += "<" + to_string(ptr->EventType + 1) + ">";
            syslog += buf;
            syslog += " ";
            syslog += "localhost"; // 主机名
            syslog += " ";
            syslog += Source;
            syslog += " ";
            syslog += "-"; // 暂不提供进程名
            syslog += " ";
            syslog += "-"; // 暂不提供 PID
            syslog += " ";
            syslog += "-"; // 暂不提供线程 ID
            syslog += " ";
            syslog += "-"; // 暂不提供消息 ID
            syslog += " ";
            syslog += message;

            cout << syslog << endl;

            i += ptr->Length;
        }
    }

    Sleep(1000); // 等待 1 秒后继续读取
}

delete[] Data;
CloseEventLog(Log);

return 0;
}

Copy

需要注意的是,上述代码中的 syslog 格式可能不完全符合实际需要,你可能需要根据自己的实际需求进行修改。此外,上述代码仅演示了如何持续获取最新的 Windows日志内容,并转换为 syslog 形式发送,但并没有实现实际的发送功能,你需要根据自己的实际需求进行添加。



```c++
#include <Windows.h>
#include <stdio.h>
 int main()
{
    HANDLE hEventLog = NULL;
    DWORD dwReadFlags = EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
    DWORD dwNumRead = 0;
    DWORD dwBytesToRead = 0;
    DWORD dwBytesRead = 0;
    DWORD dwLastError = 0;
    PVOID pRecord = NULL;
     // 打开系统事件日志
    hEventLog = OpenEventLog(NULL, "System");
    if (hEventLog == NULL)
    {
        fprintf(stderr, "OpenEventLog failed (%d)\n", GetLastError());
        return 1;
    }
     // 循环读取最新的事件日志
    while (true)
    {
        // 获取事件日志中未读取的记录数
        if (!GetNumberOfEventLogRecords(hEventLog, &dwNumRead))
        {
            fprintf(stderr, "GetNumberOfEventLogRecords failed (%d)\n", GetLastError());
            break;
        }
         // 如果没有未读取的记录,则等待1秒再次尝试
        if (dwNumRead == 0)
        {
            Sleep(1000);
            continue;
        }
         // 读取最新的事件日志记录
        dwBytesToRead = sizeof(EVENTLOGRECORD) + 4096;
        dwBytesRead = 0;
        pRecord = malloc(dwBytesToRead);
        if (ReadEventLog(hEventLog, dwReadFlags, 0, pRecord, dwBytesToRead, &dwBytesRead, &dwLastError))
        {
            // 在这里对事件日志进行处理
            printf("Event Log: %.*s\n", ((EVENTLOGRECORD*)pRecord)->Length, (char*)pRecord + ((EVENTLOGRECORD*)pRecord)->StringOffset);
        }
        else
        {
            fprintf(stderr, "ReadEventLog failed (%d)\n", dwLastError);
            break;
        }
         free(pRecord);
    }
     CloseEventLog(hEventLog);
    return 0;
}

```

该代码使用 OpenEventLog() 函数打开系统事件日志,然后循环调用 GetNumberOfEventLogRecords() 和 ReadEventLog() 函数,以获取最新的事件日志记录并进行处理。循环中通过 Sleep() 函数等待1秒,以便在没有未读取记录时等待系统写入新的记录。使用 CloseEventLog() 函数关闭系统事件日志的句柄。

这是C++实现的持续获取最新的Windows日志内容示例代码,可以参考一下

#include <iostream>
#include <windows.h>
#include <WinBase.h>
#include <WinEvt.h>

#define BUFFER_SIZE 4096   // 读取日志缓存区大小

int main()
{
    DWORD dwStatus = ERROR_SUCCESS;
    EVT_HANDLE hEvents = NULL;
    DWORD dwReturned = 0;
    DWORD dwBufferSize = BUFFER_SIZE;
    char buffer[BUFFER_SIZE] = { 0 };

    // 打开指定的Event Log。这里示例打开的是System Event Log。
    EVT_HANDLE hLog = EvtOpenLog(NULL, "System", EvtChannelSystem);

    // 循环读取最新的Event Log事件记录
    while (true)
    {
        // 获取Event Log中的最新的事件记录
        dwStatus = EvtQuery(hLog, NULL, EvtQueryReverseDirection | EvtQueryOldestFirst,
            NULL, NULL, NULL, 0, NULL);

        if (dwStatus == ERROR_SUCCESS)
        {
            hEvents = EvtSubscribe(hLog, NULL, NULL, NULL, NULL, NULL, NULL, EvtSubscribeToFutureEvents);
            while (true)
            {
                if (EvtNext(hEvents, 1, NULL, 0, dwBufferSize, buffer, &dwReturned))
                {
                    std::cout << "New Event:\n" << buffer << std::endl; // 处理新的事件记录
                }
                else
                {
                    Sleep(1000); // 没有新的事件记录,则等待1秒
                }
            }

            EvtClose(hEvents);
        }
        else
        {
            std::cerr << "Failed to query event log with error code: " << dwStatus << std::endl;
            break;
        }
    }

    EvtClose(hLog);
    return 0;
}
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/169634
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:Windows下使用命令行编译多個C++文件
  • 除此之外, 这篇博客: Windows编程---使用C/C++语言创建一个窗口中的 创建窗口 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 窗口类注册完成以后我们就可以调用CreateWindow(Ex)函数来创建窗口了

    HWND hWnd = CreateWindowEx(
        0,                        //扩展窗口风格,暂时设为0
        wc.lpszClassName,         //已注册的窗口类名称
        TEXT("Hello Windows"),    //窗口的标题
        dwStyle,                  //窗口的风格
        CW_USEDEFAULT, 
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,            //窗口的位置信息
        nullptr, 
        nullptr, 
        nullptr, 
        nullptr);
        
    ShowWindow(hWnd, SW_SHOWDEFAULT);//显示窗口
    
  • 以下回答由chatgpt基于相关博客总结生成:

    我可以提供一个参考代码示例,使用Windows的事件订阅API来实现实时获取最新的日志内容。该示例仅包含关键代码部分,需要根据实际代码架构进行修改:

    // 这里需要包含Windows事件订阅API的头文件
    
    // 定义回调函数,用于处理收到的事件
    VOID WINAPI HandleEvent(PEVENT_RECORD pEventRecord)
    {
        // 处理事件记录
        // 例如,将记录保存到文件或者数据库中
    }
    
    int main()
    {
        // 初始化事件订阅查询
        LPWSTR pQuery = L"*[System/Level=2]";
        EVT_HANDLE hSubscription, hEvent;
        hSubscription = EvtSubscribe(NULL, NULL, pQuery, NULL, NULL, NULL, HandleEvent, EvtSubscribeStartAtOldestRecord);
        if (hSubscription == NULL)
        {
            // 初始化订阅失败,处理错误
            return -1;
        }
    
        // 循环等待事件到达
        while (1)
        {
            hEvent = EvtNext(hSubscription, INFINITE, 0, 0);
            if (hEvent == NULL)
            {
                // 获取事件失败,处理错误
                break;
            }
    
            // 处理事件
            HandleEvent(hEvent);
            EvtClose(hEvent);
        }
    
        // 结束订阅
        EvtClose(hSubscription);
        return 0;
    }
    

    该示例使用Windows事件订阅API来订阅指定的日志查询,并在查询到新的事件时调用回调函数进行处理。你可以根据实际需要修改查询语句和处理事件的代码逻辑。同时,你也可以使用其他的实时获取Windows日志的方法,例如使用Windows事件日志API或者使用第三方工具等。

查询日志

#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;
}

c获取window日志

#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;
}