读取特定的Windows事件日志事件

16

我正在编写一个程序,需要知道如何根据记录号读取Windows事件日志中的特定条目,该脚本已经具备。以下是我一直在使用的代码,但我不想循环遍历所有事件直到找到我要查找的那一个。有什么想法吗?

import win32evtlog

server = 'localhost' # name of the target computer to get event logs
logtype = 'System'
hand = win32evtlog.OpenEventLog(server,logtype)
flags = win32evtlog.EVENTLOG_BACKWARDS_READ|win32evtlog.EVENTLOG_SEQUENTIAL_READ
total = win32evtlog.GetNumberOfEventLogRecords(hand)

while True:
    events = win32evtlog.ReadEventLog(hand, flags,0)
    if events:
        for event in events:
            if event.EventID == "27035":
                print 'Event Category:', event.EventCategory
                print 'Time Generated:', event.TimeGenerated
                print 'Source Name:', event.SourceName
                print 'Event ID:', event.EventID
                print 'Event Type:', event.EventType
                data = event.StringInserts
                if data:
                    print 'Event Data:'
                    for msg in data:
                        print msg
                break

1
完成后记得调用 win32evtlog.CloseEventLog(hand) - twasbrillig
4个回答

15

我知道这是一个老问题,但我偶然发现了它,如果我能找到它,别人也可能会。

您还可以编写自定义查询,让您根据任何WMI参数(包括事件ID)进行查询。 这也有助于您取出并整理所有那些VBS WMI查询。 实际上,我比任何其他功能更频繁地使用此功能。 例如,请参见:

以下是一个示例,用于在应用程序日志中查询特定事件。 我没有详细说明,但您还可以构建WMI时间字符串,并查询在特定日期/时间之间或自特定日期/时间以来的事件。

#! py -3

import wmi

def main():
    rval = 0  # Default: Check passes.

    # Initialize WMI objects and query.
    wmi_o = wmi.WMI('.')
    wql = ("SELECT * FROM Win32_NTLogEvent WHERE Logfile="
           "'Application' AND EventCode='3036'")

    # Query WMI object.
    wql_r = wmi_o.query(wql)

    if len(wql_r):
        rval = -1  # Check fails.

    return rval



if __name__ == '__main__':
    main()

考虑在您的回答中添加实际代码,并将链接仅用作参考。您希望使答案自包含,因为您不知道这些链接何时会失效。 - rayryeng
谢谢您的建议 - 我已经这么做了。 - Deacon

11

现在(适用于Python 3及以上版本)有一个名为winevt的Python库可以完成您所要求的功能。您要查找的内容可以通过以下方式实现:

from winevt import EventLog
query = EventLog.Query("System","Event/System[EventID=27035]")
event = next(query)

10

不行!没有可用的函数可以通过事件ID获取事件。

参考:事件记录函数

GetNumberOfEventLogRecords  Retrieves the number of records in the specified event log.
GetOldestEventLogRecord     Retrieves the absolute record number of the oldest record 
                            in the specified event log.
NotifyChangeEventLog        Enables an application to receive notification when an event
                            is written to the specified event log.

ReadEventLog                Reads a whole number of entries from the specified event log.
RegisterEventSource         Retrieves a registered handle to the specified event log.

另一个有用的方法是阅读最老的事件。

无论如何,您都必须遍历结果,并且您的方法是正确的 :)

您可以更改方法的形式,但这是不必要的。

events = win32evtlog.ReadEventLog(hand, flags,0)
events_list = [event for event in events if event.EventID == "27035"]
if event_list:
    print 'Event Category:', events_list[0].EventCategory

这只是你正在做的那种方式,但更加简洁。


太好了!我不久前就找到了那个信息!感谢您的回答,我会在可以的时候接受它。 - Zac Brown
2
我不知道这个答案发布时的状态如何,但现在已经不正确了(请参见下面的我的答案 - 如果您可以编写WMI查询,您可以查询它)。 - Deacon
EventID 是一个整数。它永远不会匹配字符串 "27035"。 - wojtow

1

我看到已经有答案涵盖了这些问题。但是我想补充一点,如果您需要检索特定事件时间创建的特定日志,则可以按照以下步骤执行:

import win32evtlog
from lxml import objectify
from datetime import datetime, timezone


def get_events(task_name, events_num):

    """
    task_name: a string from windows logs. e.g: "Microsoft-Windows-LanguagePackSetup/Operational"
    events_num: an integer for numbers of time creation. example: 10
    Output sample: 2022-03-09 08:45:29
    """
    handle = win32evtlog.EvtQuery(task_name, win32evtlog.EvtQueryReverseDirection , "*")
    event = win32evtlog.EvtNext(handle, 70, -1, 0)
    for i in event[-events_num:]:
        root = objectify.fromstring(win32evtlog.EvtRender(i, 1)) 
        paras =  root.System.TimeCreated
        d = datetime.fromisoformat(paras.attrib['SystemTime'][:23]).astimezone(timezone.utc)
        print(d.strftime('%Y-%m-%d %H:%M:%S'))

task_name = input("Enter the task name (e.g. Microsoft-Windows-ReadyBoost/Operational)")
events_num = int(input("Enter the number of logs"))
result = get_events(task_name, events_num)


if __name__ == "__main__": 
    print(result)

这是获取特定日志的好方法。您可以从XML文件中获得比仅时间创建更多的信息。 此网页提供了Win32扩展的简洁解释:http://timgolden.me.uk/pywin32-docs/contents.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接