开发者

Powershell - how to sort UNC paths by ping response time

I'm trying to make a script that would given a list of UNC shares order them by their ping response time. I've managed to come up with something that feels quite like a hack and I'm wondering if anyone has any better idea how to do it purely in "powershell spirit"?

This is my ugly solution:

$shares = Get-Content unc_shares.txt | where {Test-Path $_}
$servers = $shares | ForEach-Object {$_.Substring(2, $_.IndexOf("\", 3) - 2)}

$sortedServers = ($servers |
  ForEach-Object -Process {(Get-WmiObject Win32开发者_StackOverflow_PingStatus -filter "Address='$_'")} |
  sort ResponseTime |
  select Address)

foreach($server in $sortedServers)
{
  $shares | where {$_.Contains($server.Address)} | Out-File $sortedListPath -append
}


When all you want to do is sort, just use a ScriptBlock to sort by:

cat .\uncshares.txt | Sort { Test-Connection -Count 1 -CN $_.split('\')[2] }

Or, you could use an average:

cat .\uncshares.txt | Sort { Test-Connection -Count 3 -CN $_.split('\')[2] | Measure ResponseTime -Average | Select -Expand Average }

It's true that when you want to add data to an object, you should use Add-Member. In this case, you could add a NoteProperty with the result of the ping, but it's more interesting to add script property (or method) called ping that would actually execute the ping. That is, it will do the ping when you call the ping member:

$Shares = cat .\uncshares.txt | Add-Member ScriptProperty Ping -Passthru -Value {
            Test-Connection $this.split('\')[2] -Count 1 | 
            Select -Expand ResponseTime }

# Each time you sort by it, it will re-ping, notice the delay:
$Shares | Sort Ping

You can use the average with this method too:

$Shares = cat .\uncshares.txt | Add-Member ScriptProperty Ping -Passthru -Value {
            (Test-Connection $this.split('\')[2] -Count 3 | 
             Measure ResponseTime -Average).Average }

# But this will take even longer:
$Shares | Sort Ping

As an alternative to Add-Member (when you do NOT want to re-ping every time), you can build up objects using Select-Object, so you could create a Ping object, and then add the Share name back to it like so:

$unc = cat .\uncshares.txt

## Gotta love backslashes in regex. Not...
$unc -replace '\\\\([^\\]+)\\.*','$1' | 
    Test-Connection -Count 1 -CN {$_} | 
    Sort ResponseTime | 
    Select @{n='Server';e={$_.Address}},
           @{n='Share'; e={$unc -match $_.Address}},
           @{n='Ping';  e={$_.ResponseTime}}

That allows you to have drastically different output because you're combining multiple objects together...


Here's a "folded" one-liner:

   @(foreach ($unc in $list){
      test-connection $unc.split("\")[2] |
       measure responsetime -average |
        % {$_.average.tostring() + " $unc"}}) |
         sort |% {$_.split()[1]}

If you want to save and display the ResponseTimes, replace that last line with:

sort | select @{l="Share";e={$_.split()[1]}},@{l="ResponseTime";e={"{0:F2}" -f $_.split()[0]}}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜