c# - 如何找出 EventProperty 名称?

标签 c# .net windows event-log

我的 C# 应用程序订阅 Windows 事件日志消息:

var subscriptionQuery = new EventLogQuery(Settings.Default.LogPath, PathType.LogName, Settings.Default.LogQuery);
_watcher = new EventLogWatcher(subscriptionQuery);
_watcher.EventRecordWritten += EventLogEventRead;

当消息发生时,EventLogEventRead 处理程序会重新接收包含事件数据的 System.Diagnostics.Eventing.Reader.EventLogRecord 对象。此信息包括 EventProperty 对象的集合。 问题是:EventProperty 只定义了一个值,而不是属性的名称。但是,当我在 Windows 事件日志查看器中打开同一事件时,它会显示带有名称的属性。 现在的问题是:如何获取事件属性名称?

最佳答案

我终于明白了! 🎉 您打算使用 EventLogPropertySelector指定 XPath 表达式以选择所需的属性。然后,不调用 EventRecord.Properties,而是调用 EventLogRecord.GetPropertyValues(EventLogPropertySelector) .返回值通过索引与您在创建 EventLogPropertySelector 时指定的 XPath 表达式相关联。

有关显示 XPath 表达式应该是什么样子的 C++ 示例,请参阅 https://learn.microsoft.com/windows/desktop/WES/rendering-events :

...

LPWSTR ppValues[] = {L"Event/System/Provider/@Name", L"Event/System/Channel"};
DWORD count = sizeof(ppValues)/sizeof(LPWSTR);

// Identify the components of the event that you want to render. In this case,
// render the provider's name and channel from the system section of the event.
// To get user data from the event, you can specify an expression such as
// L"Event/EventData/Data[@Name=\"<data name goes here>\"]".
hContext = EvtCreateRenderContext(count, (LPCWSTR*)ppValues, EvtRenderContextValues);

...

这是一个 C# 示例,它演示了只为每种事件类型提取所需的值:

var query = new EventLogQuery(
    "Security",
    PathType.LogName,
    "*[System[EventID=4624 or EventID=4634]]");

using (var loginEventPropertySelector = new EventLogPropertySelector(new[]
{
    // (The XPath expression evaluates to null if no Data element exists with the specified name.)
    "Event/EventData/Data[@Name='TargetUserSid']",
    "Event/EventData/Data[@Name='TargetLogonId']",
    "Event/EventData/Data[@Name='LogonType']",
    "Event/EventData/Data[@Name='ElevatedToken']",
    "Event/EventData/Data[@Name='WorkstationName']",
    "Event/EventData/Data[@Name='ProcessName']",
    "Event/EventData/Data[@Name='IpAddress']",
    "Event/EventData/Data[@Name='IpPort']"
}))
using (var logoffEventPropertySelector = new EventLogPropertySelector(new[]
{
    "Event/EventData/Data[@Name='TargetUserSid']",
    "Event/EventData/Data[@Name='TargetLogonId']"
}))
using (var reader = new EventLogReader(query))
{
    // In C# 8: while (reader.ReadEvent() is { } ev)
    while (reader.ReadEvent() is var ev && ev != null)
    {
        using (ev)
        {
            switch (ev.Id)
            {
                case 4624:
                {
                    var loginPropertyValues = ((EventLogRecord)ev).GetPropertyValues(loginEventPropertySelector);
                    var targetUserSid = (SecurityIdentifier)loginPropertyValues[0];
                    // ...
                    break;
                }
                case 4634:
                {
                    var logoffPropertyValues = ((EventLogRecord)ev).GetPropertyValues(logoffEventPropertySelector);
                    var targetUserSid = (SecurityIdentifier)logoffPropertyValues[0];
                    // ...
                    break;
                }
            }
        }
    }
}

这几乎无法被发现(除了缺少 .NET 文档之外)的原因是 EventLogReader.ReadEvent 返回 EventRecord,然后您必须将其转换为 事件日志记录。这就是我在查看 .NET Framework 源代码并看到 EventRecord.Properties 最终 p/invokes EvtRender 时的线索。 . https://learn.microsoft.com/windows/desktop/api/winevt/nf-winevt-evtrender#remarks :

There is a one-to-one relationship between the array of XPath expressions that you specified when you called the EvtCreateRenderContext function and the array the values returned in the buffer.

关于c# - 如何找出 EventProperty 名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31488175/

相关文章:

c# - 将 C# 锯齿状数组转换为数组并再次返回

java - java Windows服务 "know"如何完成初始化?

c# - 读取sql cel,查找行ID并更新同一行中的单元格

c# - 在 C# 中反射?

c# - ServiceStack.OrmLite : Where is the method to write custom SQL and get result set back?

c# - 何时以及如何使用 lock()?

c# - 如何根据当前服务器找到最适合读取或写入 Stream 的缓冲区大小

.net - 采用标准库

windows - 批处理脚本冒险

windows - Apache Cassandra 进程在 Windows 上是如何命名的?