Summary: Ed Wilson, Microsoft Scripting Guy, talks about parsing output from NetStat with Windows PowerShell 5.0.
Hey, Scripting Guy! I need a good way to parse output from the NetStat command. I use it all the time, but it ends up requiring me to spend a lot of time looking through stuff. I am not sure if the command itself has a filter language or what, but I really need to be able to parse on the fly.
I have even gone so far as run the command, copy it to the clipboard, paste it into Notepad, and then go through the Notepad file adding characters so I could import it into Excel and filter the output. But obviously, that is a lot of work. I really need to be able to see stuff like what connections are open, closed, and suspended. Can you help me?
—JK
Hello JK,
Microsoft Scripting Guy, Ed Wilson, is here. It hasn’t started raining yet, but I am sure it will. I mean, summer in central Florida? There are two things one can count on: an afternoon thunder storm and humidity. Lots and lots of humidity. I am not sure what people did before air conditioning around here. Maybe they lived in St. Augustine where they could go to the beach every day.
Anyway, just like I can count on a summer thunderstorm in central Florida, I can also count on the fact that I am going to have to parse text at some point. Luckily that task just took a giant leap towards simplicity with the new ConvertFrom-String cmdlet in Windows PowerShell 5.0.
JK, parsing output from NetStat just got a whole lot easier. In the past, I have written complicated scripts to parse the output from NetStat. I mean it was nearly 20 or so lines long, and it took me a couple of days to accomplish it—but in the end, I was able to output objects that permitted me to filter my output. It was worth it. But as of Windows PowerShell 5.0, the script is completely obsolete.
Capture the output
The first thing I want to do is to capture the output from NetStat. I like to store the results from the command into a variable because the output from NetStat is always a bit slow appearing. By capturing the output into a variable, I can effectively work offline. This command is shown here:
$a = netstat
When I look at the output from the information stored in my variable, I can see that there are a couple of lines that I do not need:
PS C:\> $a
Active Connections
Proto Local Address Foreign Address State
What I want is an easy way to skip the first few lines, but keep the remainder of the output. Luckily, I know exactly how many lines are in the variable—it is $a.count. So, I create a range that skips the first few lines, and continues to the end of my data. This is shown here:
PS C:\> $a[3..$a.count]
Proto Local Address Foreign Address State
TCP 192.168.0.2:56798 bn1wns2011304:https ESTABLISHED
TCP 192.168.0.2:56852 bn1wns1011219:https ESTABLISHED
TCP 192.168.0.2:57076 a184-27-27-179:https ESTABLISHED
TCP 192.168.0.2:57080 a184-29-178-13:https CLOSE_WAIT
<truncated>
Now I need to convert the output to objects by using the ConvertFrom-String cmdlet. By default, it will use spaces to create a property on the new object. This is great, because my output from NetStat is delimited by spaces. But, when I look at my output, I see that there must be a leading space, so P1 is empty:
PS C:\> $a[3..$a.count] | ConvertFrom-String
P1 :
P2 : Proto
P3 : Local
P4 : Address
P5 : Foreign
P6 : Address
P7 : State
P1 :
P2 : TCP
P3 : 192.168.0.2:56798
P4 : bn1wns2011304:https
P5 : ESTABLISHED
P1 :
P2 : TCP
P3 : 192.168.0.2:56852
P4 : bn1wns1011219:https
P5 : ESTABLISHED
<truncated>
I simply use Select-Object to select properties P2, P3, P4, and P5:
$a[3..$a.count] | ConvertFrom-String | select p2,p3,p4,p5
The output from the command is shown here:
Now I can easily filter by any property value I want. For example, I can filter the output for connections that are established. As you can see here, I add where P5 –eq ‘established’:
$a[3..$a.count] | ConvertFrom-String | select p2,p3,p4,p5 | where p5 -eq 'established'
The command and its output are shown here:
I can look for things related to mail:
$a[3..$a.count] | ConvertFrom-String | select p2,p3,p4,p5 | where p4 -match 'mail'
…or a specific part of an IP address, such as this command that finds IP addresses that begin with the number 23:
$a[3..$a.count] | ConvertFrom-String | select p2,p3,p4,p5 | where p4 -match '^23'
When I have my output from NetStat converted into true objects, I can use the entire power of Windows PowerShell to search through the objects and find exactly what I need—and I can do it all in a series of one-liners. That truly is the power of PowerShell.
JK, that is all there is to using ConvertFrom-String to help parse NetStat output. Join me tomorrow when I will talk about more way cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Hi Dr Scripto,
Thank you for the post!
I just wanted to share the one-liner I use:
$RawNetstat=netstat -ano; $Unrefined = $RawNetstat[4..$(($RawNetstat|measure).count)] | ConvertFrom-String -PropertyNames EmptyProperty1,Proto,LocalAddress,ForeignAddress,State,PID; $NetstatResult = $Unrefined | ? {$_.Proto -eq “TCP”} | select *,@{l=”ProcessName”;e={(get-process -id $_.PID).ProcessName}} -ExcludeProperty EmptyProperty1; $NetstatResult | ft
Regards,
O