.netpowershellevent-logtraceetw

Get Windows event provider information


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.


Solution

  • 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):

    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:

    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:

    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:

    ...

    $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:

    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];