2017-06-12 236 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

相關問題