JNA 从 windows 事件日志记录中解析描述字符串
JNA parse description strings from windows event log record
我正在使用 JNA 读取我的应用程序传送的一些事件日志。我最感兴趣的是描述字符串数据。
我正在使用以下代码:
private static void readLog() {
Advapi32Util.EventLogIterator iter = new Advapi32Util.EventLogIterator("Application");
while (iter.hasNext()) {
Advapi32Util.EventLogRecord record = iter.next();
System.out.println("------------------------------------------------------------");
System.out.println(record.getRecordNumber()
+ ": Event ID: " + record.getInstanceId()
+ ", Event Type: " + record.getType()
+ ", Event Strings: " + Arrays.toString(record.getStrings())
+ ", Data: " + record.getRecord().toString());
System.out.println();
}
}
我的应用程序产生的示例事件:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-MyApp" Guid="{4d5ae6a1-c7c8-4e6d-b840-4d8080b42e1b}" />
<EventID>201</EventID>
<Version>0</Version>
<Level>2</Level>
<Task>2</Task>
<Opcode>30</Opcode>
<Keywords>0x4010000001000000</Keywords>
<TimeCreated SystemTime="2021-02-19T15:16:03.675690900Z" />
<EventRecordID>3622</EventRecordID>
<Correlation ActivityID="{e6ee2b3b-9b9a-4c9d-b39b-6c2bf2550000}" />
<Execution ProcessID="2108" ThreadID="8908" />
<Channel>Microsoft-Windows-MyApp/Operational</Channel>
<Computer>computer</Computer>
<Security UserID="S-1-5-20" />
</System>
<UserData>
<EventInfo xmlns="aag">
<Username>username</Username>
<IpAddress>127.0.0.1</IpAddress>
<AuthType>NTLM</AuthType>
<Resource />
<ConnectionProtocol>HTTP</ConnectionProtocol>
<ErrorCode>23003</ErrorCode>
</EventInfo>
</UserData>
</Event>
其他事件用户数据:
<UserData>
<EventInfo xmlns="aag">
<Username>otherUserName</Username>
<IpAddress>10.235.163.52:50427</IpAddress>
</EventInfo>
</UserData>
JNA 在EVENTLOGRECORD
class 中提供事件日志记录,其中仅包含仅获取描述字符串值的方法。如果我能得到 XML 格式的记录,我的问题就会消失。
UserData 中的数据并不总是相同的,它包含不同的值,具体取决于事件类型。我想将 UserData 部分的数据解析为 POJO(它可以只是一个包含所有可用字段的 POJO)。我不想使用字段顺序,因为有些事件的字段与其他事件不同(如示例所示)。
有什么方法可以使用 xml 标签名来做到这一点吗?我什至会考虑切换到其他语言。
正如我在评论中指出的,您需要 render the event to get to the XML. Matthias Bläsing 还指出一些示例代码在 JNA 的 WevtapiTest
测试 class 中可用。
使用该测试 class,我创建了以下程序,它从系统日志的最新 50 个事件中读取 XML。将事件过滤为您想要的内容留作 reader.
的练习。
public static void main(String[] args) {
EVT_HANDLE queryHandle = null;
// Requires elevation or shared access to the log.
String path = "C:\Windows\System32\Winevt\Logs\System.evtx";
try {
queryHandle = Wevtapi.INSTANCE.EvtQuery(null, path, null, Winevt.EVT_QUERY_FLAGS.EvtQueryFilePath);
// Read 10 events at a time
int eventArraySize = 10;
int evtNextTimeout = 1000;
int arrayIndex = 0;
EVT_HANDLE[] eventArray = new EVT_HANDLE[eventArraySize];
IntByReference returned = new IntByReference();
while (Wevtapi.INSTANCE.EvtNext(queryHandle, eventArraySize, eventArray, evtNextTimeout, 0, returned)) {
Memory buff;
// This just needs to be 0. Kept same name from test sample
IntByReference propertyCount = new IntByReference();
Winevt.EVT_VARIANT evtVariant = new Winevt.EVT_VARIANT();
for (int i = 0; i < returned.getValue(); i++) {
buff = WevtapiUtil.EvtRender(null, eventArray[i], Winevt.EVT_RENDER_FLAGS.EvtRenderEventXml,
propertyCount);
// Output the XML!
System.out.println(buff.getWideString(0));
}
arrayIndex++;
// Quit after 5 x 10 events
if (arrayIndex >= 5) {
break;
}
}
if (Kernel32.INSTANCE.GetLastError() != WinError.ERROR_SUCCESS
&& Kernel32.INSTANCE.GetLastError() != WinError.ERROR_NO_MORE_ITEMS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
} finally {
if (queryHandle != null) {
Wevtapi.INSTANCE.EvtClose(queryHandle);
}
}
}
我正在使用 JNA 读取我的应用程序传送的一些事件日志。我最感兴趣的是描述字符串数据。
我正在使用以下代码:
private static void readLog() {
Advapi32Util.EventLogIterator iter = new Advapi32Util.EventLogIterator("Application");
while (iter.hasNext()) {
Advapi32Util.EventLogRecord record = iter.next();
System.out.println("------------------------------------------------------------");
System.out.println(record.getRecordNumber()
+ ": Event ID: " + record.getInstanceId()
+ ", Event Type: " + record.getType()
+ ", Event Strings: " + Arrays.toString(record.getStrings())
+ ", Data: " + record.getRecord().toString());
System.out.println();
}
}
我的应用程序产生的示例事件:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-MyApp" Guid="{4d5ae6a1-c7c8-4e6d-b840-4d8080b42e1b}" />
<EventID>201</EventID>
<Version>0</Version>
<Level>2</Level>
<Task>2</Task>
<Opcode>30</Opcode>
<Keywords>0x4010000001000000</Keywords>
<TimeCreated SystemTime="2021-02-19T15:16:03.675690900Z" />
<EventRecordID>3622</EventRecordID>
<Correlation ActivityID="{e6ee2b3b-9b9a-4c9d-b39b-6c2bf2550000}" />
<Execution ProcessID="2108" ThreadID="8908" />
<Channel>Microsoft-Windows-MyApp/Operational</Channel>
<Computer>computer</Computer>
<Security UserID="S-1-5-20" />
</System>
<UserData>
<EventInfo xmlns="aag">
<Username>username</Username>
<IpAddress>127.0.0.1</IpAddress>
<AuthType>NTLM</AuthType>
<Resource />
<ConnectionProtocol>HTTP</ConnectionProtocol>
<ErrorCode>23003</ErrorCode>
</EventInfo>
</UserData>
</Event>
其他事件用户数据:
<UserData>
<EventInfo xmlns="aag">
<Username>otherUserName</Username>
<IpAddress>10.235.163.52:50427</IpAddress>
</EventInfo>
</UserData>
JNA 在EVENTLOGRECORD
class 中提供事件日志记录,其中仅包含仅获取描述字符串值的方法。如果我能得到 XML 格式的记录,我的问题就会消失。
UserData 中的数据并不总是相同的,它包含不同的值,具体取决于事件类型。我想将 UserData 部分的数据解析为 POJO(它可以只是一个包含所有可用字段的 POJO)。我不想使用字段顺序,因为有些事件的字段与其他事件不同(如示例所示)。
有什么方法可以使用 xml 标签名来做到这一点吗?我什至会考虑切换到其他语言。
正如我在评论中指出的,您需要 render the event to get to the XML. Matthias Bläsing 还指出一些示例代码在 JNA 的 WevtapiTest
测试 class 中可用。
使用该测试 class,我创建了以下程序,它从系统日志的最新 50 个事件中读取 XML。将事件过滤为您想要的内容留作 reader.
的练习。 public static void main(String[] args) {
EVT_HANDLE queryHandle = null;
// Requires elevation or shared access to the log.
String path = "C:\Windows\System32\Winevt\Logs\System.evtx";
try {
queryHandle = Wevtapi.INSTANCE.EvtQuery(null, path, null, Winevt.EVT_QUERY_FLAGS.EvtQueryFilePath);
// Read 10 events at a time
int eventArraySize = 10;
int evtNextTimeout = 1000;
int arrayIndex = 0;
EVT_HANDLE[] eventArray = new EVT_HANDLE[eventArraySize];
IntByReference returned = new IntByReference();
while (Wevtapi.INSTANCE.EvtNext(queryHandle, eventArraySize, eventArray, evtNextTimeout, 0, returned)) {
Memory buff;
// This just needs to be 0. Kept same name from test sample
IntByReference propertyCount = new IntByReference();
Winevt.EVT_VARIANT evtVariant = new Winevt.EVT_VARIANT();
for (int i = 0; i < returned.getValue(); i++) {
buff = WevtapiUtil.EvtRender(null, eventArray[i], Winevt.EVT_RENDER_FLAGS.EvtRenderEventXml,
propertyCount);
// Output the XML!
System.out.println(buff.getWideString(0));
}
arrayIndex++;
// Quit after 5 x 10 events
if (arrayIndex >= 5) {
break;
}
}
if (Kernel32.INSTANCE.GetLastError() != WinError.ERROR_SUCCESS
&& Kernel32.INSTANCE.GetLastError() != WinError.ERROR_NO_MORE_ITEMS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
} finally {
if (queryHandle != null) {
Wevtapi.INSTANCE.EvtClose(queryHandle);
}
}
}