获取Windows事件提供程序信息。

3
我想使用Windows PowerShell检索有关事件提供程序的信息。我正在运行Windows 8.1,PowerShell版本为4.0,并且我注意到在System.Diagnostics.Eventing命名空间中有一些.NET类提供了一些关于Windows事件的功能。
我可以通过调用其默认构造函数创建一个EventProvider实例,但这并不能让我获取有关安装在系统上的事件提供程序的任何信息。
$EventProvider = New-Object -TypeName System.Diagnostics.Eventing.EventProvider -ArgumentList ([System.Guid]'{00000000-0000-0000-0000-000000000000}');

如何使用Windows PowerShell获取有关已安装在系统上的Event Tracing for Windows(ETW)提供程序的更多信息,并与Windows事件日志进行交互?

我已经知道可以使用命令logman.exe query providers,如此处所述,检索ETW提供程序列表并查询Windows事件日志,但这不太适用于PowerShell。

3个回答

13
有另一个名为System.Diagnostics.Eventing.Reader的.NET命名空间,其中包含许多更多的.NET类,可让您检索有关在Windows操作系统上注册的事件跟踪(ETW)提供程序和事件日志的信息。这些类型中的大部分是在.NET程序集中的全局程序集缓存(GAC)中定义的System.Core.dll

例如,您可以执行以下操作(等等):

  • 查找计算机上安装的ETW提供程序的名称
  • 发现计算机上存在的完整ETW日志名称列表
  • 枚举与ETW提供程序相关的元数据
  • 导出事件日志数据

ETW提供程序名称

核心功能之一是获取已安装在给定系统上的ETW提供程序列表。您可以使用位于System.Diagnostics.Eventing.Reader命名空间中的.NET Framework类型轻松检索此信息。恰好有一个名为EventLogSession的.NET类,该类具有名为GlobalSession的静态属性,该属性自动检索与本地计算机上的事件日志服务的会话/连接。如果需要,您还可以使用EventLogSession类上的构造函数之一连接到远程计算机。
一旦检索到EventLogSession类的实例,就可以调用GetProviderNames()方法检索代表计算机上已安装的ETW提供程序名称的String对象集合。
以下是从本地计算机检索提供程序名称的示例:
$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
$EventProviderNames = $EventSession.GetProviderNames();
$EventProviderNames;

这是一个使用替代构造函数从远程计算机检索ETW提供程序名称的示例:
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList server01.contoso.com;
$EventProviderNames = $EventSession.GetProviderNames();
$EventProviderNames;

您可以使用 EventLogSession 类的另一个构造函数来指定远程计算机的备用凭据。 EventLogSession 类的 alternate constructor 需要以下参数:
  • 计算机名称
  • 域名
  • 用户名
  • 密码(作为 SecureString
  • System.Diagnostics.Eventing.Reader.SessionAuthentication 类型
下面是如何实现的示例:
$ComputerName = 'server01.contoso.com';
$Credential   = Get-Credential;
$ArgumentList = $ComputerName, $Credential.UserName.Split('\')[0], $Credential.UserName.Split('\')[1], $Credential.Password, [System.Diagnostics.Eventing.Reader.SessionAuthentication]::Default;
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList $ArgumentList;

ETW日志名称

一旦您发现计算机上安装的所有ETW提供程序,您可能还希望探索计算机上可用的完整ETW日志列表。 EventLogSession类还具有一个名为GetLogNames()的方法,该方法返回表示目标系统上可用的ETW日志的String对象集合。与GetProviderNames()方法类似,您可以在本地或远程计算机上调用GetLogNames()

以下是从本地计算机检索ETW日志名称的示例:

$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
$EventLogNames = $EventSession.GetLogNames();
$EventLogNames;

以下是从远程计算机检索ETW日志名称的示例:
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList server01.contoso.com;
$EventLogNames = $EventSession.GetLogNames();
$EventLogNames;

ETW提供程序元数据

除了检索ETW提供程序名称外,您可能还希望检索有关它们的更详细信息。您可以使用System.Diagnostics.Eventing.Reader .NET类中的ProviderMetadata类来实现此目的。由ProviderMetadata类提供的信息包括:

  • 提供程序显示名称
  • 帮助链接(URL)
  • 提供程序的关键字
  • ETW提供程序ID(GUID)
  • 消息文件路径
  • 资源文件路径
  • 参数文件路径
  • 提供程序公开的任务
  • 提供程序声明的每个事件的事件元数据

与ETW提供程序和ETW日志名称类似,您可以从本地或远程系统中检索提供程序元数据。在后一种情况下,您必须在尝试实例化ProviderMetadata类之前建立一个EventLogSession实例。

以下是从本地系统检索ETW提供程序元数据的示例:

# Get the EventLogSession object
$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
# Get the ETW provider names
$EventProviderNames = $EventSession.GetProviderNames();

# Create an empty array to hold the ProviderMetadata instances
$ProviderMetadataList = @();
# For each ETW provider name ...
foreach ($EventProvider in $EventProviderNames) {
    # Add each ProviderMetadata instance to the array
    $ProviderMetadataList += New-Object -TypeName System.Diagnostics.Eventing.Reader.ProviderMetadata -ArgumentList $EventProvider;
}

# Explore the 16th item from the ProviderMetadata array
$ProviderMetadataList[15];

要从远程系统检索ETW提供程序元数据,请在实例化ProviderMetadata类之前构建您的EventLogSession对象,并且当您实例化ProviderMetadata时,请确保将以下参数传递给constructor

  • ETW提供程序名称
  • EventLogSession实例
  • CultureInfo对象

...

$ComputerName = 'server01.contoso.com';
$Credential   = Get-Credential;
$SessionArgumentList = $ComputerName, $Credential.UserName.Split('\')[0], $Credential.UserName.Split('\')[1], $Credential.Password, [System.Diagnostics.Eventing.Reader.SessionAuthentication]::Kerberos;
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList $SessionArgumentList;
$EventProviderNames = $EventSession.GetProviderNames();

# Create an empty array to hold the ProviderMetadata instances
$ProviderMetadataList = @();
foreach ($EventProvider in $EventProviderNames) {
    # Build the Arguments for the ProviderMetadata constructor
    $ProviderMetadataArgumentList = $EventProvider, $EventSession, [CultureInfo]::CurrentCulture;
    # Add each ProviderMetadata instance to the array
    $ProviderMetadataList += New-Object -TypeName System.Diagnostics.Eventing.Reader.ProviderMetadata -ArgumentList $ProviderMetadataArgumentList;
}

# Explore the 111th item from the array
$ProviderMetadataList[110];

注意:当您通过已认证的连接实例化ProviderMetadata对象时,可能会出现一些异常:
“New-Object:使用3个参数调用“.ctor”时发生异常:“尝试执行未经授权的操作。””
读取ETW事件日志
由于您提到您也想从ETW事件日志中读取事件,因此可以使用System.Diagnostics.Eventing.Reader .NET命名空间中的类型轻松完成此操作。EventLogReader类包含一个名为ReadEvent()的方法,该方法在实例化EventLogReader时指定的事件日志中连续读取下一个事件。
以下是从System事件日志中读取事件的简单示例:
# Instantiate the EventLogReader .NET class
$EventLogReader = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogReader -ArgumentList 'System';
# Read the first 5 events from the event log
1..5 | % { $EventLogReader.ReadEvent(); };

ETW事件日志配置

与先前检索的提供程序元数据类似,您可以检索有关特定ETW事件日志配置的信息。要做到这一点,您需要实例化EventLogConfiguration,并传入ETW事件日志的名称。将返回有关事件日志的各种信息,包括:

  • 日志名称
  • 最大大小(以字节为单位)
  • 提供程序名称
  • 日志类型
  • 安全描述符
  • 缓冲区大小
  • 是否启用日志?

以下是检索此信息的示例:

$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
$EventLogNames = $EventSession.GetLogNames();

$EventLogConfigurationList = @();
foreach ($EventLogName in $EventLogNames) {
    $EventLogConfigurationList += New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogConfiguration -ArgumentList $EventLogName;
}
$EventLogConfigurationList[5];

我猜这是针对Vista及以上系统的。在XP上尝试时,会出现“不支持”的异常。 - Mohan Kumar
我在寻找特定提供商的消息DLL,而你成功了。谢谢! - FranciscoNabas

0

我花了好几个小时试图找出如何从提供程序名称中找到源名称 - 例如,Get-WinEvent 显示这个复杂的名称“Microsoft-Windows-User Profiles Service”,而事件日志显示一个友好的名称,比如“用户配置文件服务”,然后我意识到。

事件日志只是删除了“Microsoft-Windows-”,这就是为什么源显示名称像“Security-SPP”一样有破折号,因为提供程序名称“Microsoft-Windows-Security-SPP”在去掉“Microsoft-Windows-”后有一个破折号。

对于操作系统的非英文版本也是如此。

唉。


0
# working in version 5
$providers = Get-WinEvent -ListProvider * | select name
$providers

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