Every network admin will at some point need to capture and view network events to help troubleshoot network issues. The PowerShell module NetEventPacketCapture is an interesting option to capture network traces

IT professionals have many tools that can enable the capturing and viewing of network traffic. Tools such as Wireshark and Netmon have been staples for performing network traces. Starting with Windows 7/2008 the netsh trace command became available to allow capturing traces via the command line.

The NetEventPacketCapture module ^

One tool I have recently started using is the PowerShell NetEventPacketCapture module to capture and show trace events. Microsoft released the module with Windows 8.1/2012 R2, so although it is a few years old, it is not a widely used tool. One of the main reasons why using this module is appealing to me is that you can do many of the tasks within PowerShell without having to use other tools.

In order to create a trace log (.etl file), you must use four cmdlets from the NetEventPacketCapture module. In addition, you need a tool to view the trace file. This would be the bare minimum process for capturing a network event trace:

  • Use New-NetEventSession to create a trace session. For remote traces you can use the ‑CimSession
  • Add-NetEventProvider to add an event-tracing provider to the session you created. For instance the provider "Microsoft-Windows-TCPIP" would trace TCP/IP events.
  • Start-NetEventSession will begin logging live events to the .etl file.
  • Stop-NetEventSession will end the trace session.
  • Finally, to view the .etl file, you can use a number of tools. In this article, I will use the Get-WinEvent cmdlet in PowerShell.

Capturing a SMB client trace ^

In this example, I want to capture and view Server Message Block (SMB) client events on a remote computer. Before I move forward, I need to know which provider to use for my session. To view a list of the providers, I can run the command logman query providers. After running this command on my machine, I see I have about 830 providers! I will use the Microsoft-Windows-SMBClient provider to capture and view traces on my remote machine Test-1.

First I create a new Common Information Model (CIM) session to my remote computer with New-CimSession.

C:\> $Cim = New-CimSession -ComputerName 'Test-1'

Next, I create a new event session. Notice I use the same CIM session I just created as well as the -LocalFilePath parameter to specify where to save the ".etl" file.

C:\> New-NetEventSession -Name "Session01" -CimSession $Cim -LocalFilePath "C:\Windows\Temp\Trace.etl" -CaptureMode SaveToFile

Name               : Session01
CaptureMode        : SaveToFile
LocalFilePath      : C:\Windows\Temp\Trace.etl
MaxFileSize        : 250 MB
TraceBufferSize    : 0 KB
MaxNumberOfBuffers : 0
SessionStatus      : NotRunning
PSComputerName     : Test-1

Now I will add the SMB client provider so I can capture SMB client events.

C:\> Add-NetEventProvider -CimSession $Cim -Name 'Microsoft-Windows-SMBClient' -SessionName "Session01"

Name            : Microsoft-Windows-SMBClient
SessionName     : Session01
Level           : 4
MatchAnyKeyword : 0xFFFFFFFFFFFFFFFF
MatchAllKeyword : 0x0
PSComputerName  : Test-1

To start and stop the trace session, I use Start-NetEventSession and Stop-NetEventSession, remembering to specify the CIM session for both.

C:\> Start-NetEventSession -Name "Session01" -CimSession $Cim 
C:\> Stop-NetEventSession -Name "Session01" -CimSession $Cim

Finally, it is time to display the trace log. For this I can use the Get-WinEvent cmdlet and point to the path on my remote machine.

C:\> Get-WinEvent -Path "\\Test-1\C$\Windows\Temp\trace1.etl" -Oldest

Using the Invoke-PSTrace function ^

While it is not difficult to capture a trace using the cmdlets, it is much more efficient if we create a PowerShell function to automate capturing a trace. With this function, I just have to specify the computer name and provider to use for the trace. The only other interaction is stopping the trace, for which I use a simple Read-Host command. I also included the option of opening the trace file in Microsoft Message Analyzer with the -OpenWithMessageAnalyzer parameter.

The one advanced technique I use in this function is a dynamic parameter for choosing an Event Tracing for Windows (ETW) provider. This was to simplify the task of finding the name of the provider to use, since dynamic parameters allow tab completion. This enables me to tab through the many providers.

To create the array of the providers, I use the command logman query provider. Using this command alone prints out the provider name and GUID. I piped this to a foreach loop to cut out the GUID text as well as the header and "The command completed successfully" message that displays at the end.

#requires -Modules NetEventPacketCapture

function Invoke-PSTrace {
    [OutputType([System.Diagnostics.Eventing.Reader.EventLogRecord])]
    [CmdletBinding()]

    param(
        [Parameter(Mandatory=$true)]
        [string]$ComputerName,
        [switch]$OpenWithMessageAnalyzer,
        [pscredential]$Credential
    )  
        DynamicParam 
        {
            $ParameterName = 'ETWProvider' 
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $AttributeCollection.Add($ParameterAttribute)
            $arrSet = logman query providers | Foreach-Object {$_.split('{')[0].trimend()} | Select-Object -Skip 3 | Select-Object -SkipLast 2
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)
            $AttributeCollection.Add($ValidateSetAttribute)
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
            return $RuntimeParameterDictionary
        }
    begin 
    {
        $ETWProvider = $PsBoundParameters[$ParameterName]
    }

    process 
    {
        #Remove any existing sessions
        Get-CimSession -ComputerName $ComputerName -ErrorAction SilentlyContinue | Remove-CimSession -Confirm:$False
        Get-NetEventSession -Name "Session1" -ErrorAction SilentlyContinue | Remove-NetEventSession -Confirm:$False
        Remove-Item -Path "C:\Windows\Temp\$ComputerName-Trace.etl" -Force -Confirm:$False -ErrorAction SilentlyContinue
        #Create new session
        try 
        {
            $Cim = New-CimSession -ComputerName $ComputerName -Credential $Credential -ErrorAction Stop
            New-NetEventSession -Name "Session1" -CimSession $Cim -LocalFilePath "C:\Windows\Temp\$ComputerName-Trace.etl" -ErrorAction Stop -CaptureMode SaveToFile | Out-Null
        }
        catch 
        {
            Write-Error $_
            Break
        }    
        Add-NetEventProvider -CimSession $Cim -Name $ETWProvider -SessionName "Session1" | Out-Null
        Start-NetEventSession -Name "Session1" -CimSession $Cim | Out-Null
        if (Get-NetEventSession -CimSession $Cim)
        {
            Read-Host 'Press enter to stop trace' | Out-Null
        }
        Stop-NetEventSession -Name 'Session1' -CimSession $Cim   
        Remove-NetEventProvider -Name $ETWProvider -CimSession $Cim  
        Remove-NetEventSession -Name 'Session1' -CimSession $Cim  
        Remove-CimSession -CimSession $Cim -Confirm:$False 
        if ($ComputerName -ne 'LocalHost')
        {
            Copy-Item -Path "\\$ComputerName\C$\Windows\Temp\$ComputerName-trace.etl" -Destination 'C:\Windows\Temp' -Force
        }
        Get-CimSession -ComputerName $ComputerName -ErrorAction SilentlyContinue | Remove-CimSession -Confirm:$False
        if ($OpenWithMessageAnalyzer)
        {
             Start-Process -FilePath 'C:\Program Files\Microsoft Message Analyzer\MessageAnalyzer.exe' -ArgumentList "C:\Windows\Temp\$ComputerName-trace.etl"
        }
        else 
        {
             Get-WinEvent -Path "C:\Windows\Temp\$ComputerName-trace.etl" -Oldest 
        }
    }
}

In this example of using Invoke-PSTrace, I run a trace on my remote machine "Test-2" while using the "Microsoft-Windows-TCPIP" provider.

Subscribe to 4sysops newsletter!

Output of Invoke PSTrace

Output of Invoke PSTrace

avataravatar
0 Comments

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account