2017-06-12 47 views
2

我创建了一个脚本来输出Get-NetTCPConnection数据,但另外显示进程名称用户名。该脚本确实的工作,但我会喜欢任何提示,以简化或使这更加规范。PowerShell的:获取NetTCPConnection脚本,也显示用户名和进程名称

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

[email protected]() 

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

+1

有一个代码审查stackexchange网站,这可能更适合FYI。很酷的想法btw。 –

+0

我不知道。对不起,如果这篇文章是OT。 MODS,随时移动它! – luckman212

回答

1

我找不到在代码审查的问题,所以我在这里张贴的答案的时刻。

使用字典(散列表)可简化表达式并改进每个pid的查找时间。

[email protected]{} 

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

模式:

$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

感谢你们,我用我自己的实现挣扎着ArgumentTransformationMetadataException错误。使用你的代码作为起点,我已经扩展它来查询udp和tcp守护进程及其相关进程。在此处查看http://jcutrer.com/howto/dev/powershell/network-daemons-parent-processes – JCutrer

+0

@JC_谢谢! - 这是一个很酷的脚本,我使用了很多netstat,并会尝试使用它:) – TessellatingHeckler

相关问题