Turning NETSTAT results into an Object

A customer was trying to extract some data from the netstat command. The customer had already formed part of the syntax, but needed some additional assistance with filtering out the values they wished to see.

Let’s take a look at the results of the netstat –nao command

 

In this case, the customer wanted to filter only on “Listening” ports. They had already accomplished this by piping the netstat –nao command to the select-string cmdlet

Netstat –nao | select-string “Listening”

They wanted to further filter down the list by looking for only certain ports. Again, this was accomplished by piping the resulting into another select-string cmdlet.

netstat -nao | Select-String "Listening" | Select-String ":80|:3389|:445" 

 

The next part is where the big challenge comes in. The customer only wanted the data from Columns 2 and 5. This would be the bound IP and listening Port and the associated PID. Since we are using netstat the data returned is just text, there is not native way to select those columns.

In order to do this, we need to extract the data we want from the lines. We came up with two solutions, the 1 liner and turning the data into an object.

 

Let’s start with the 1 liner.

netstat -nao | Select-String "Listening" | Select-String ":80|:3389|:445" | % {$a = $_ -split '\s\s*' ; write-host "$($a[2]), $($a[5])" } 

In this case, we are piping the results to a foreach (% - alias) loop, and then splitting the value of each line into an array using the whitespace as a delimiter. We are using the regular expression (\s\s*) to identify contiguous whitespace between the column. The remaining values from the split are stored as an array in the $a variable. We then want to write out columns 2 and 5 to the console.

Although this does provide the desired output, it’s not very pretty.

 

Let’s see turn these results into an object instead.

$ListeningPort = @()

$GetPorts = netstat -nao | Select-String "Listening" | Select-String ":80|:3389|:445" 

     Foreach ($Port in $GetPorts) {

    $a = $Port -split '\s\s*'

    $Ports = New-Object System.Object

    $Ports | Add-Member -MemberType NoteProperty -Name 'BoundIP:Port' -Value $a[2]

    $Ports | Add-Member -MemberType NoteProperty -Name 'PID' -Value $a[5]

   

    $ListeningPort += $Ports

  }

 $ListeningPort

 

 

This takes a little more work, put provides much better output. First, we create a variable ($ListeningPort) as an empty array to hold our objects.

$ListeningPort = @()

 

Then we take our command to filter the NETSTAT command to the rows we are interested in and store those in the $GetPorts variable.

$GetPorts = netstat -nao | Select-String "Listening" | Select-String ":80|:3389|:445" 

Now we run the results through a ForEach loop and for each line, we still split on the whitespace ('\s\s*') and store that data into $a. 

Foreach ($Port in $GetPorts) {

       $a = $Port -split '\s\s*'

After that, we create a System.Object and add two properties for the object, BoundPort:IP and PID. We store the split data in positions 2 and 5 from $a are value in the object.

    $Ports = New-Object System.Object

  $Ports | Add-Member -MemberType NoteProperty -Name 'BoundIP:Port' -Value $a[2]

  $Ports | Add-Member -MemberType NoteProperty -Name 'PID' -Value $a[5]

 

We then stuff the resulting object $Ports into the array ($ListeningPorts) that we initialized in the beginning. 

$ListeningPort += $Ports

The ForEach loop does this for each line from NETSTAT that matches our Select-String queries. The resulting array of objects $ListeningPorts provides a nice clean, exportable output.

 

This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.