如何找出EventProperty名称?

时间:2015-07-18 05:42:39

标签: c# .net windows event-log

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

---- PersonTable.xaml.cs ----

[ViewToViewModel(MappingType = ViewToViewModelMappingType.ViewModelToView]
public ObservableCollection<PersonItem> PersonItems { get { ... } }

---- PersonTable.xaml ----

<CollectionViewSource Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PersonTable}}, Path=PersonItems}" ...... >

当出现消息时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只定义一个值,而不是属性的名称。但是,当我在Windows事件日志查看器中打开相同的事件时,它会显示带有名称的属性。 现在的问题是:我如何获得事件名称?

2 个答案:

答案 0 :(得分:2)

有两种方法可以解决这个问题(我知道),但都涉及解析xml。

EventRecord的函数ToXml包含UserData部分,其中包含该块中的所有值。

另一种选择有点复杂: 创建ProviderMetadata,找到描述当前EventMetadata的{​​{1}},然后解析EventRecord成员。 这个Template成员解释了如何解释这些值(甚至包括类型),但它是XML格式的。

Template

答案 1 :(得分:1)

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

有关显示XPath表达式外观的C ++示例,请参见https://docs.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,然后您必须将其转换为EventLogRecord。这就是让我了解.NET Framework源代码并发现EventRecord.Properties最终p /调用EvtRender的原因。 https://docs.microsoft.com/windows/desktop/api/winevt/nf-winevt-evtrender#remarks

  

您在调用EvtCreateRenderContext函数时指定的XPath表达式数组与该数组在缓冲区中返回的值之间存在一对一的关系。