I would like to retrieve information about event providers using Windows PowerShell? I'm running Windows 8.1 with PowerShell version 4.0, and I noticed that there are some .NET classes in the System.Diagnostics.Eventing
namespace that offer some functionality around Windows eventing.
I can create an EventProvider
instance by calling its default constructor, however this does not allow me to get any information about the event providers installed on the system.
$EventProvider = New-Object -TypeName System.Diagnostics.Eventing.EventProvider -ArgumentList ([System.Guid]'{00000000-0000-0000-0000-000000000000}');
How can I get more information about Event Tracing for Windows (ETW) providers that are installed on a system, and interact with Windows event logs, using Windows PowerShell?
I am already aware that I can use the command logman.exe query providers
, as described here, to retrieve the ETW provider list, and query the Windows event logs, but this is not very PowerShell friendly.
There is another .NET namespace called System.Diagnostics.Eventing.Reader
, which contains a lot more .NET classes that allow you to retrieve information about Event Tracing for Windows (ETW) providers and event logs that are registered with a Windows operating system. Most of these types are defined in the System.Core.dll
.NET Assembly in the .NET Global Assembly Cache (GAC).
For example, you can perform the following actions (and more):
- Find out the names of ETW providers installed on a computer
- Discover a complete list of ETW log names present on a computer
- Enumerate metadata related to ETW providers
- Export event log data
ETW Provider Names
One of the core functions with ETW is getting a list of ETW providers are that are installed on a given system. You can easily retrieve this information with the .NET Framework types in the System.Diagnostics.Eventing.Reader
namespace. There just so happens to be a .NET class named EventLogSession
, and on this class is a static property named GlobalSession
, which automatically retrieves a session/connection to the Event Log service on the local computer. If necessary, you can alternatively connect to a remote computer by using one of the constructors on the EventLogSession
class.
Once you have retrieved an instance of the EventLogSession
class, you can call the GetProviderNames()
method to retrieve a collection of String
objects that represent the names of the installed ETW providers on the computer.
Here is an example of retrieving the provider names from the local computer:
$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
$EventProviderNames = $EventSession.GetProviderNames();
$EventProviderNames;
Here is an example of retrieving the ETW provider names from a remote computer using an alternate constructor:
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList server01.contoso.com;
$EventProviderNames = $EventSession.GetProviderNames();
$EventProviderNames;
You can use a different constructor of the EventLogSession
class to specify alternate credentials to the remote computer. The alternate constructor for the EventLogSession
class requires the following parameters:
- Computer name
- Domain name
- User name
- Password (as a
SecureString
)
System.Diagnostics.Eventing.Reader.SessionAuthentication
type
Here is an example of how to achieve that:
$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 Log Names
Once you have discovered all of the ETW providers installed on a computer, you may also wish to explore a complete list of the ETW logs that available on a computer. The EventLogSession
class also has a method called GetLogNames()
, which returns a collection of String
objects that represent the ETW logs available on a target system. Similar to the GetProviderNames()
method, you can call GetLogNames()
on a local or remote computer.
Here is an example of retrieving the ETW log names from the local computer:
$EventSession = [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession;
$EventLogNames = $EventSession.GetLogNames();
$EventLogNames;
Here is an example of retrieving the ETW log names from a remote computer:
$EventSession = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogSession -ArgumentList server01.contoso.com;
$EventLogNames = $EventSession.GetLogNames();
$EventLogNames;
ETW Provider Metadata
In addition to retrieving ETW provider names, you might also wish to retrieve more detailed information about them. You can do this using the ProviderMetadata
class in the System.Diagnostics.Eventing.Reader
.NET class. Information provided by the ProviderMetadata
class includes:
- Provider display name
- Help link (URL)
- Keywords for the provider
- ETW provider ID (GUID)
- Message file path
- Resource file path
- Parameter file path
- Tasks exposed by the provider
- Event metadata for each event declared by the provider
Similar to the ETW provider and ETW log names, you can retrieve provider metadata from the local or remote system. In the latter case, you must establish an EventLogSession
instance before you attempt to instantiate the ProviderMetadata
class.
Here is an example of retrieving ETW provider metadata from the local system:
# 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];
To retrieve ETW provider metadata from a remote system, build your EventLogSession
object before instantiating the ProviderMetadata
class, and when you do instantiate ProviderMetadata
, make sure you pass in the following parameters to the constructor:
- ETW provider name
EventLogSession
instance
- A
CultureInfo
object
...
$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];
Note: You might get some exceptions when you instantiate ProviderMetadata
objects through authenticated connections:
New-Object : Exception calling ".ctor" with "3" argument(s): "Attempted to
perform an unauthorized operation."
Reading ETW Event Logs
Since you mentioned that you wanted to read events from ETW event logs also, this is easy to do with the types in the System.Diagnostics.Eventing.Reader
.NET namespace as well. The EventLogReader
class contains a method called ReadEvent()
which continually reads the next events from the event log specified when the EventLogReader
was instantiated.
Here is a simple example of reading events from the System event log:
# 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 Event Log Configuration
Similar to the provider metadata retrieved earlier, you can retrieve information about the configuration of a particular ETW event log. To do this, you instantiate the EventLogConfiguration
class, passing in the name of an ETW event log. A variety of information about the event log will be returned, including:
- Log name
- Maximum size (in bytes)
- Provider name(s)
- Log type
- Security descriptor
- Buffer size
- Is log enabled?
Here is an example of how to retrieve this information:
$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];