JosefZ's answer perfectly explains your issue. You are using regex and it is doing exactly what you are asking it to do just perhaps replacing more than you expected.
A side note is that you are asking netstat
to
displays the executable involved in creating each connection or listening port
with the b switch. However you are dropping that with select-string
since that process appears on its own line after the other data. That is not the end of the world but because you can use things like -Context
of Select-String
to get that but that will have to be looked at more closely another time.
I would like to offer other suggestions as to what you can do in this situation.
Using other tools is unfortunately not possible so I'm limited to using built-in Windows tools.
Funny thing about that, do you have at least Windows 8? If you do you could just use the Get-NetTCPConnection
cmdlet which is essentially netstat
in object form.
So you could do this which should get you the same information without the hassle
get-nettcpconnection | select local*,remote*,state,@{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}}
Don't have Windows 8+? Well then we could improve on your parsing script. Taking it one step further to create object will prevent issue with regex matching.
netstat -ano | Where-Object{$_ -match 'LISTENING|UDP'} | ForEach-Object{
$split = $_.Trim() -split "\s+"
[pscustomobject][ordered]@{
"Proto" = $split[0]
"Local Address" = $split[1]
"Foreign Address" = $split[2]
# Some might not have a state. Check to see if the last element is a number. If it is ignore it
"State" = if($split[3] -notmatch "\d+"){$split[3]}else{""}
# The last element in every case will be a PID
"Process Name" = $(Get-Process -Id $split[-1]).ProcessName
}
}
If you were limited to PowerShell v2 then you would need to change the psobject and ordered casts
netstat -ano | Where-Object{$_ -match 'LISTENING|UDP'} | ForEach-Object{
$split = $_.Trim() -split "\s+"
New-Object -Type pscustomobject -Property @{
"Proto" = $split[0]
"Local Address" = $split[1]
"Foreign Address" = $split[2]
# Some might not have a state. Check to see if the last element is a number. If it is ignore it
"State" = if($split[3] -notmatch "\d+"){$split[3]}else{""}
# The last element in every case will be a PID
"Process Name" = $(Get-Process -Id $split[-1]).ProcessName
}
} | Select "Proto", "Local Address", "Foreign Address", "State", "Process Name"
The last select
statement guarantees the property order, which would be shuffled otherwise, and is the functional equivalent to [ordered]
So that will net you output like this...
Proto Local Address Foreign Address State Process Name
----- ------------- --------------- ----- ------------
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING svchost
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING System
TCP 0.0.0.0:1279 0.0.0.0:0 LISTENING PlexDlnaServer
TCP 0.0.0.0:2869 0.0.0.0:0 LISTENING System
Which you can then treat like you would any PowerShell object and filter as you see fit or output to CSV or whatever you need to do. It is structured now.
Depending on your PowerShell version you can also use Convert-FromString
which takes single line strings and converts them to objects as well. Something else to look up.
netstat -bano|select-string 'LISTENING|UDP'