【问题标题】:PowerShell: Get-NetTCPConnection script that also shows Username & Process NamePowerShell:Get-NetTCPConnection 脚本,还显示用户名和进程名称
【发布时间】:2017-06-12 21:44:36
【问题描述】:

我创建了一个脚本来输出 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

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

【问题讨论】:

  • 有一个代码审查 stackexchange 站点,这可能更适合仅供参考。顺便说一句,好主意。
  • 我不知道。对不起,如果这篇文章是 OT。模组,随意移动!

标签: windows powershell netstat


【解决方案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

【讨论】:

    【解决方案2】:

    图案:

    $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 作为字符串返回,因此需要进行哈希表查找的转换。

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

    【讨论】:

    • 感谢您,我在自己的实现中遇到了 ArgumentTransformationMetadataException 错误。使用您的代码作为起点,我已将其扩展为查询 udp 和 tcp 守护进程及其相关进程。在这里查看jcutrer.com/howto/dev/powershell/…
    • @JC_ 谢谢! - 这是一个很酷的脚本,我经常使用 netstat 并且会尝试使用它:)
    【解决方案3】:

    我在 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
    

    【讨论】:

      【解决方案4】:
      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
      

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

      【讨论】:

        猜你喜欢
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 2019-11-26
        • 1970-01-01
        • 1970-01-01
        • 2021-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多