从事件日志中读取任务计划程序事件

时间:2018-11-30 19:14:42

标签: c winapi event-log taskscheduler

我想列出C / C ++中任务计划程序的自定义任务的所有已执行运行。因此,我访问事件日志并尝试提取TaskScheduler日志条目,如下所示(为简单起见,删除了所有错误处理):

HANDLE hEv = OpenEventLogA(NULL, "Microsoft-Windows-TaskScheduler/Operational");
DWORD nrRead = 0x10000, status = ERROR_SUCCESS, nrMin = 0, nrDone;
PBYTE buf = (PBYTE) malloc(nrRead);
while (status == ERROR_SUCCESS) {
  if (!ReadEventLog(hEv, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 
    0, buf, nrRead, &nrDone, &nrMin)) status = GetLastError();

  for (PBYTE pRec = buf, pEnd = buf + nrRead; pRec < pEnd;) {
    (void) (pRec + sizeof(EVENTLOGRECORD));     // Store record
    pRec += ((PEVENTLOGRECORD) pRec)->Length;
    if (((PEVENTLOGRECORD) pRec)->Length == 0) break; // Avoid endless loop
  }
}

实际上,我能够从日志(例如WiFi日志)中读取事件。但是我无法打开TaskScheduler日志。然后按照文档中的说明进行操作,并退回到应用程序日志。

我为日志名称尝试了不同的字符串:

  • 事件日志中的协议名称
  • 以斜杠分隔的协议路径
  • 英文名称和本地化名称

似乎都不起作用。那么如何打开TaskScheduler日志?日志名称是否已本地化并且需要根据当前的操作系统语言进行调整?还有另一种方法来检索TaskScheduler执行吗?

2 个答案:

答案 0 :(得分:1)

我已经尝试过您的代码,好像OpenEventLog只能打开一些经常使用的日志(不确定)。但是,还有另一种方法列出TaskScheduler事件:

使用train_review = train['review'] train_token = '' for i in train['review']: train_token += str(i) 添加回调函数,查询记录时,以XML格式将其打印出来。这是代码示例:

EvtSubscribe()

希望它可以为您提供帮助!

答案 1 :(得分:0)

感谢@ zett42指向正确的方向,感谢@Drake Wu给出详细的代码示例。但是由于我不需要任何将来的事件或异步检索,所以我现在实现了一个简单的同步函数:

#define EVT_SIZE 10

int GetEvents(LPCWSTR query) {
    DWORD xmlLen = 0;
    LPCWSTR xml = NULL;
    EVT_HANDLE hQuery = EvtQuery(NULL, NULL, query, EvtQueryChannelPath | EvtQueryTolerateQueryErrors));

    while (true) {
        EVT_HANDLE hEv[EVT_SIZE];
        DWORD dwReturned = 0;
        if (!EvtNext(hQuery, EVT_SIZE, hEv, INFINITE, 0, &dwReturned)) return 0;

        // Loop over all events
        for (DWORD i = 0; i < dwReturned; i++) {
            DWORD nrRead = 0, nrProps = 0;

            if (!EvtRender(NULL, hEv[i], EvtRenderEventXml, xmlLen, xml, &nrRead, &nrProps)) {
                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                    xmlLen = nrRead;
                    xml = (LPWSTR) realloc(xml, xmlLen);
                    if (xml) {
                        EvtRender(NULL, hEv[i], EvtRenderEventXml, xmlLen, xml, &nrRead, &nrProps);
                    } else {
                        return -1;
                    }
                }
                if (GetLastError() != ERROR_SUCCESS) return -1;
            }

            // Store event data

            EvtClose(hEv[i]);
            hEv[i] = NULL;
        }
    }
    return 0;
}

同样,为了简化示例,我删除了大多数错误处理。 Evt *函数确实可以用于TaskScheduler数据的检索(独立于语言)。