简体   繁体   中英

PowerShell Test-Connection -efficient Method

One Bronze medal = Newbi, have scoured this site for years, so a million belated thanks, once again!

Just finished up a few different PowerShell ver 5.1 scripts that perform a test-connection on the same 2000 devices regularly.

Out to a csv file

And they are all slow, some minor speed improvements when tweaking it down to the bare bones.

I've scaled the script to the minimal, IPADDRESS and NAME only

I've run a few comparison tests against a batch file (ping 123.456.789.001 >> PingTest.txt ) and these tests APPEAR to run quicker than my PS script (will run a full apple to apples test tomorrow), but confident something is amiss in the PS code.

Am looking at arrays, and how piping works, but am afraid I'm putting the cart in front of the horse, or there is something going on with how PS handles the csv format and/or ping list in its memory

My most efficient current script below,

Is the following link pointing me in the right direction,? Specifically the asJob switch

PowerShell Mass Test-Connection


$info = "" | Select IPaddress,Name
$OutputFile = new-item -itemType File -path  C:\Temp\Results.csv -force -value "IPaddress,Name`r`n" | out-null
 
Import-csv C:\Temp\GetList.csv | ForEach-Object {
if ($_.IPaddress) {
 
if (-Not (Test-Connection -ComputerName $_.IPaddress -Quiet -Count 2 -ErrorAction SilentlyContinue)) {
$info.IPaddress = $_.IPaddress
$info.Name = $_.Name

add-content -value "$($info.IPaddress),$($info.Name)"  -path C:\Temp\Results.CSV
}
}
} 

The export-csv is faster, thank you. I'm not sure if I have it in the right place, but it works, will run some tests on it tomorrow. I may have to include the passes tests though, still getting my head around the get-job cmdlet.

$info = "" | Select IPaddress,Name,Status

Import-csv c:\Temp\GetList.csv | ForEach-Object {
if($_.Ipaddress) {

if (-Not(Test-Connection -ComputerName $_.IPaddress -Quiet -Count 2 -ErrorAction SilentlyContinue)) {

$info.IPaddress = $_.IPaddress
$info.Name = $_.Name
$info.Status = "Failed"
$info | export-csv C:\Temp\Results1.csv -Force -Notypeinformation -Append
}
}
}
$list = Import-Csv C:\Temp\GetList.csv
ForEach ($item In $list) {
  Start-Job -ScriptBlock {
    param($item)
    if (Test-Connection -Computername $item.IPaddress -Quiet -Count 1) {
      Add-Content -value "$($item.IPaddress),$($item.Name),$($item.Stauts)" -Path C:\Temp\xlistlist.csv
      $list | Export-csv c:\Temp\xCSvreults.csv -Force -NoTypeInformation -Append
    }
  } -argumentlist $list
}

Thanks Santiago, I did some exploring here, just ran out of time for the day. THANK YOU you for the code examples they cleared a few things up for me:-) – Have Computer Dec 2 at 3:59

Would you mind adding some inline comments so I can follow along? Just trynna understand multi-threading (using runspaces) a bit better. – Abraham Zinala Dec 2 at 4:58 1

@AbrahamZinala is there a specific part you're struggling to understand? i'm not an expert on this and wouldn't like to give false information. Might be better to pick up all the parts you don't understand and ask a new question – Santiago Squarzon Dec 2 at 12:19

Nah man, sorry, I figured it out lol – Abraham Zinala Dec 2 at 13:43 1

@AbrahamZinala the only hard part to understand is the [powershell] instance part imo, and you can think of it as a Start-Job but much faster and less memory consuming, you add your scriptblock with.AddScript({...}) and then the parameters with.AddParameters([hashtablehere]). It's important to save the PSInstance in a variable so that we can get the output out of it and it's handler (Status = $psinstance.BeginInvoke()) to know when the instance has completed. The rest is just pure blueprint, once you have one you can copy paste it:P – Santiago Squarzon Dec 2 at 13:50

@HaveComputer I have no idea what your comment means. – Santiago Squarzon Dec 5 at 1:10 the 2 solutions presented work much faster, my code however is lacking. – Have Computer Dec 5 at 1:16

@HaveComputer I know that, this can perform 50x faster or even more depending on hardware and bandwidth. – Santiago Squarzon

This is a good place where you can use runspaces , I would love to test if Test-Connection -AsJob performs better than this but for some reason it is not available on PS Core on Linux.

Code below took around 10 seconds to scan 254 IPs using my private network IP range. There is a lot of tweaking that can be done, ie you can poke around the $Threshold variable, it's currently running 100 runspaces at a time, Count and TimeoutSeconds for Test-Connection have been set to 2 you can tweak that too.

$results variable can be exported using Export-Csv .

# Change this value for tweaking
$Threshold = 100
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $Threshold)
$RunspacePool.Open()

# This is for testing, use your CSV here instead
# => $list = Import-Csv C:\Temp\GetList.csv
$list = 1..254 | ForEach-Object {
    [pscustomobject]@{
        IPAddress = "192.168.1.$_"
        Hostname = "ExampleHost$_"
    }
}

$scriptBlock = {
    param($ip, $hostname)

    $params = @{
        Quiet = $true
        Count = 2
        TimeoutSeconds = 2
        ComputerName = $ip
    }

    $status = Test-Connection @params

    [pscustomobject]@{
        Hostname = $hostname
        IPAddress = $ip
        Status = ('Failed','Success')[[int]$status]
    }
}

$runspaces = foreach($line in $list)
{
    $params = @{
        ip = $line.IPAddress
        hostname = $line.Hostname
    }

    $psinstance = [powershell]::Create().AddScript($scriptBlock).AddParameters($params)
    $psinstance.RunspacePool = $RunspacePool
    
    [pscustomobject]@{
        Instance = $psinstance
        Status = $psinstance.BeginInvoke()
    }
}

while($runspaces.Status.IsCompleted -contains $false)
{
    Start-Sleep -Milliseconds 500
}

$results = $runspaces.ForEach({ $_.Instance.EndInvoke($_.Status) })
$RunspacePool.Dispose()

$results Sample:

Hostname       IPAddress     Status
--------       ---------     ------
ExampleHost1   192.168.1.1   Success
ExampleHost2   192.168.1.2   Failed
ExampleHost3   192.168.1.3   Success
ExampleHost4   192.168.1.4   Failed
ExampleHost5   192.168.1.5   Success
ExampleHost6   192.168.1.6   Failed
ExampleHost7   192.168.1.7   Failed
ExampleHost8   192.168.1.8   Failed
ExampleHost9   192.168.1.9   Failed
ExampleHost10  192.168.1.10  Failed
...
...
Start-Job -ScriptBlock { Test-Connection -computername  (Get-Content -Path “C:\Temp\GetList.csv”) }
~~~

its lacking the fundamentals, works, DE fast, thank you gent's 

Still working on my code, I did find this read wile working on it, run space read.

https://devblogs.microsoft.com/scripting/beginning-use-of-powershell-runspaces-part-1/

Interesting, bit long, so I recommend a beverage:-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM