PowerShell:Get-NetTCPConnection脚本,同时显示用户名和用户名。进程名称

时间:2017-06-12 21:44:37

标签: windows powershell netstat

我创建了一个脚本来输出Get-NetTCPConnection数据,但另外还显示了流程名称用户名。脚本 可以工作,但我希望有任何提示可以简化或使其更具规范性。

我想知道是否有更有效的方法将ProcessNameUsername添加到输出中,而不必将值预加载到自定义PSObject($obj数组)中。我担心自定义e={($obj |? PID -eq $_.OwningProcess | select -ExpandProperty UserName)}}表达式过于复杂。

$obj=@()

Foreach($p In (Get-Process -IncludeUserName | where {$_.UserName} | `
  select Id, ProcessName, UserName)) {
      $properties = @{ 'PID'=$p.Id;
                       'ProcessName'=$p.ProcessName;
                       'UserName'=$p.UserName;
                     }
      $psobj = New-Object -TypeName psobject -Property $properties
      $obj+=$psobj
  }

Get-NetTCPConnection | where {$_.State -eq "Established"} | select `
  RemoteAddress, `
  RemotePort, `
  @{n="PID";e={$_.OwningProcess}}, @{n="ProcessName";e={($obj |? PID -eq $_.OwningProcess | select -ExpandProperty ProcessName)}}, `
  @{n="UserName";e={($obj |? PID -eq $_.OwningProcess | select -ExpandProperty UserName)}} |
  sort -Property ProcessName, UserName |
  ft -auto

这是一个带有一些示例输出的屏幕截图:

screenshot

4 个答案:

答案 0 :(得分:3)

模式:

$a = @()
foreach ($x in Get-Thing|..) {
    $z = ..
    $a += $z
}

不是很好,因为数组上的+=会将所有内容中的大量内存中复制到新数组中,因此它可能会非常慢。 foreach() {}有时可以比| ForEach-Object {}运行得更快,但是如果你在()部分内部有一个管道并且数组添加正在进行,那么它可能不会有太大的不同。典型的替代方案:

$a = foreach ($x in Get-Thing|..) {
    $z = $x...
    $z
}

$a = Get-Thing | .. | ForEach-Object {
    $_..
}

脚本的前半部分几乎没有任何内容:

  • 以过程对象数组开头
  • 过滤掉没有用户名的内容,即使空的用户名在以后的脚本中不会改变任何内容
  • 选择三个属性,将它们从一个对象复制到一个新的自定义对象中,即使该脚本不会受到其他属性的影响。
  • 将相同的三个属性带入哈希表..
  • 将哈希表转换回自定义对象,让您回到选择后的位置。
  • 把它放回另一个阵列,但是慢慢地。

原文:数组中的进程对象。

结果:根据您使用它们的方式,调整了数组中的进程对象,但没有任何意义。

所以你可以放弃仅$obj = Get-Process -IncludeUsername的所有内容,它会起作用。

  • 你不需要那么多的反推行来继续行。 PowerShell非常擅长于有意义的继续行 - 管道|之后,以及数组中的逗号之后,包括select属性数组。这很好,因为如果后面有任何空格,反引号就会断开,很难看到。

但是如果你想要预处理使脚本的其余部分更好,使用哈希表,那么第二部分中的查找会变得更短更清晰:

# Make a lookup table by process ID
$Processes = @{}
Get-Process -IncludeUserName | ForEach-Object {
    $Processes[$_.Id] = $_
}

Get-NetTCPConnection | 
    Where-Object { $_.State -eq "Established" } |
    Select-Object RemoteAddress,
        RemotePort,
        @{Name="PID";         Expression={ $_.OwningProcess }},
        @{Name="ProcessName"; Expression={ $Processes[[int]$_.OwningProcess].ProcessName }}, 
        @{Name="UserName";    Expression={ $Processes[[int]$_.OwningProcess].UserName }} |
    Sort-Object -Property ProcessName, UserName |
    Format-Table -AutoSize

无论如何,现在这与@avvi的答案相同,我不得不停止写它但是因为在我看到他们的答案之前我无法工作 - Get-Process将Id作为数字返回Get-NetTCPConnection将OwningProcess作为字符串返回,因此需要进行哈希表查找的转换。

无论如何都要发布关于循环/数组构建的讨论。

答案 1 :(得分:2)

我在Code Review中找不到问题,所以我暂时在这里发布答案。

使用字典(哈希表)可以简化表达式并改善每个pid的查找时间。

$dict=@{}

Foreach($p In (Get-Process -IncludeUserName | where {$_.UserName -ne $null} | `
  select Id, ProcessName, UserName)) {
      $properties = @{ 'PID'=$p.Id;
                       'ProcessName'=$p.ProcessName;
                       'UserName'=$p.UserName;
                     }
      $psobj = New-Object -TypeName psobject -Property $properties
      $dict[$p.Id] = $psObj

  }

Get-NetTCPConnection | where {$_.State -eq "Established"} | select `
  RemoteAddress, `
  RemotePort, ` 
  @{n="PID";e={$_.OwningProcess}}, 
  @{n="ProcessName";e={ $dict[[int]$_.OwningProcess].ProcessName }}, `
  @{n="UserName"; e={ $dict[[int]$_.OwningProcess].UserName }} |
  sort -Property ProcessName, UserName | ft -auto

答案 2 :(得分:1)

get-nettcpconnection | select local*,remote*,state,@{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}}

我不能相信这种解决方案,我在这里找到了它:https://superuser.com/questions/1215093/powershell-one-liner-to-show-process-on-same-line-as-port-using-netstat-issue/1215237

答案 3 :(得分:0)

Get-NetTCPConnection| 
Select LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess 
, @{n="ProcessName";e={(Get-Process -Id $_.OwningProcess).ProcessName}} 
, @{n="UserName";e={(Get-Process -Id $_.OwningProcess -IncludeUserName).UserName}}| 
Where {$_.State -eq"Established"} 
|FT -autosize -Force

比清洁更清洁。在每一行的末尾添加后面的勾号(`)或删除回车并放一行。这里的反引号似乎抛弃了格式化,你必须添加两个反引号(``)来保持格式化。