我想阅读已归档的Windows事件日志文件(.evtx
),如下例所示:
using System;
using System.Diagnostics.Eventing.Reader;
public static class Program {
static void Main(string[] args) {
using (var reader = new EventLogReader(@"C:\tmp\some-log.evtx", PathType.FilePath)) {
EventRecord record;
while ((record = reader.ReadEvent()) != null) {
// do something with record...
}
}
}
}
record
对象有一个Properties
列表,其中包含事件的替换字符串:
foreach (var property in record.Properties) {
Console.WriteLine(property.Value);
}
如果我在事件日志查看器中打开.evtx
文件,我可以看到该事件的完整描述,这类似于基本模板消息(应该来自与生成的应用程序关联的资源文件)事件),占位符的值替换为这些值:
有没有办法可以为特定事件获取此“消息模板”?
答案 0 :(得分:1)
如果您在与保存事件日志不同的机器上检查事件日志,那么您将无法享受 EventLogSession.GlobalSession.GetProviderNames()
,但前提是您可以找到并安装机器的 {{1} } 注册表配置单元(位于 HKEY_LOCAL_MACHINE
文件中 - 是的,它是一个无扩展名的文件)您可以从此注册表项中获取事件模板:
C:\Windows\System32\config\SYSTEM
其中 HKEY_LOCAL_MACHINE\SYSTEM\{controlSet}\Services\EventLog\{eventLogName}\{providerName}
通常是“{controlSet}
”,但如果您正在调查在神秘情况下死亡的机器,您可能需要查看其他键,例如 CurrentControlSet
.
其中 ControlSet001
是您正在查看的日志的名称。仅为单个目标日志注册事件源。
其中 {eventLogName}
对应于 Windows 事件日志查看器中“事件源”列中的值。
查找名为 {providerName}
的注册表值,它为您提供包含 Win32 资源字符串的 Win32 PE(EventMessageFile
或 *.exe
)的路径,该字符串包含事件日志消息模板 - 您然后可以使用标准的 Win32 资源函数或其他一些库读取那些来提取 Win32 资源。
答案 1 :(得分:0)
我后来发现那些“消息模板”可以读取与某个提供者相关的事件元数据(这基本上是一个注册的事件来源)。
以下是一个例子:
using System;
using System.Diagnostics.Eventing.Reader;
using System.Globalization;
public static class Program {
static void Main(string[] args) {
foreach (var providerName in EventLogSession.GlobalSession.GetProviderNames()) {
DumpMetadata(providerName);
}
}
private static void DumpMetadata(string providerName) {
try {
ProviderMetadata providerMetadata = new ProviderMetadata(providerName, EventLogSession.GlobalSession, CultureInfo.InvariantCulture);
foreach (var eventMetadata in providerMetadata.Events) {
if (!string.IsNullOrEmpty(eventMetadata.Description)) {
Console.WriteLine("{0} ({1}): {2}", eventMetadata.Id, eventMetadata.Version, eventMetadata.Description);
}
}
} catch (EventLogException) {
Console.WriteLine("Cannot read metadata for provider {0}", providerName);
}
}
}