//代码是想持续只读取最新的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;
}
窗口类注册完成以后我们就可以调用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);//显示窗口
我可以提供一个参考代码示例,使用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;
}