Here’s a template (of sorts) that should be fairly easy to modify to suit your own needs, that solves the dilemma of running a command across multiple systems and having to wait for each one to finish before moving onto the next. This is particularly problematic when running WMI commands which takes 2-10 seconds per device to return results. This script, in theory could be used to run the command on all servers at the same time – quite the time saver.
The example below takes a network address (eg: 10.50.18.0) and pings all devices from .1 through to .254 (with each being pinged in its own parallel thread).
You could change this to be a group of Active Directory Computers, or well, any array of objects; and run commands against all of them in parallel.
NOTE: Even though we’re incrementing through the host addresses from 1 to 254, the parallel nature of what we’re doing means that some threads will likely finish out of order, and the results you get back will be somewhat random. IE; you could get results for 10.50.18.220 before 10.50.18.219 is returned.
And I’ve also included a progress bar, because, why not.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# Gather network address (must end in .0) $network = read-host "Enter network address"; $networkcheck = $network.substring($network.length-2); if ($networkcheck -eq ".0") { # Drop the .0 from the network address $network = $network.substring(0,$network.length-1); # Create Runspace Pool with 500 threads $pool = [RunspaceFactory]::CreateRunspacePool(1, 500) $pool.ApartmentState = "MTA" $pool.open() $runspaces = @() # The script you want run against each host $scriptblock = { # Take the IP address as a parameter param ([string]$ip); # Ping IP address $online = test-connection $ip -count 1 -ea 0; # Print IP address if online if ($online) { $ip; } } # Loop through numbers 1 to 254 foreach ($hostnumber in 1..254) { # Set full IP address $ip = $network + $hostnumber; $runspace = [powershell]::create() # Add script block to runspace (use $null to avoid noise) $null = $runspace.addscript($scriptblock) # Add IP address as an argument to the scriptblock (use $null to avoid noise) $null = $runspace.addargument($ip) # Add/create new runspace $runspace.runspacepool = $pool $runspaces += [pscustomobject]@{pipe=$runspace; Status=$runspace.begininvoke() } } # Prepare the progress bar $currentcount = 0; $totalcount = ($runspaces | measure-object).count; # Pause until all runspaces have completed while ($runspaces.status -ne $null) { $completed = $runspaces | where { $_.status.iscompleted -eq $true }; # Update progress bar $currentcount = $currentcount + ($completed | measure-object).count; write-progress -activity "Pinging IP Addresses..." -percentcomplete (([int]$currentcount/[int]$totalcount)*100); # Clear completed runspaces foreach ($runspace in $completed) { $runspace.pipe.endinvoke($runspace.status) $runspace.status = $null } } # Clean-up Runspace Pool $pool.close(); $pool.dispose(); } else { write-host "NOT A VALID NETWORK ADDRESS" -foregroundcolor "red" -backgroundcolor "black"; } |
The result will be a list of IP addresses that were successfully pinged, displayed to the screen: