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

问题描述 投票:2回答:4

我创建了一个脚本来输出Get-NetTCPConnection数据,但另外还显示了Process Name和Username。该脚本确实有效,但我希望有任何提示可以简化或使其更具规范性。

我想知道是否有更有效的方法将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

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

windows powershell netstat
4个回答
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作为字符串返回,因此需要对哈希表查找进行转换。

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


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

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


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

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

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.