-1

I have a PowerShell loop that does effectively what I want it to. The problem is that the output is very messy. I work for an ISP and one of the most effective ways we have to diagnose network issues is via multiple pings.

The problem is that setting up multiple pings can be messy. Rather than trying to reinvent the wheel, I'm seeking to create a simple PowerShell script that will provide an easy to digest output based on a list of IP addresses.

Here is the code I currently have:

# Define a list of IP addresses and hostnames to ping
$targets = Get-Content -Path C:\Users\Chad\Desktop\IPs.txt

# Loop through each target and ping it
 while (1) {
    foreach ($target in $targets) {
        ping $target -n 1

    }
}

I won't say my code is particularly elegant or groundbreaking. All I need to know is if there is a way to export the results for the pings to a .csv where each column represents one IP address, and the rows represent the latency for each particular ping.

The idea is that I can train my peers on how to use this script and that the .csv will not be opened until the pings are manually stopped. I'm fully open to completely reformulating how I am approaching this problem as well.

Any help is appreciated!

3 Answers 3

1

Try using powershell's Test-Connection instead, which outputs handy objects:

$targets = Get-Content -Path C:\Users\Chad\Desktop\IPs.txt

# Loop through each target and ping it
# I use -AsJob to force failed pings to get included in results
$job = Test-Connection -ComputerName $targets -Count 1 -AsJob
$results = $job | Wait-Job | Receive-Job

$results | Export-CSV c:\folder\results.csv

Looks like

Source    Destination   IPV4Address   IPV6Address Bytes Time(ms)
------    -----------   -----------   ----------- ----- --------
MyDevice  bogus                                   32            
MyDevice  myServer1     10.0.0.2                  32    65      
MyDevice  MyServer2     10.0.0.3                  32    68      
5
  • So, as above I would prefer to use the Ping command for this, but I am seeing that there is a major roadblock I am going to have to get over. Here is the modified version of your code that I tried to use: { # Define a list of IP addresses and hostnames to ping $targets = @("8.8.8.8","9.9.9.9") # Loop through each target and ping it # I use -AsJob to force failed pings to get included in results while (1) { $job = ping $target -n 1 -AsJob $results = $job | Wait-Job | Receive-Job $results | Export-CSV c:\Users\Chad\Desktop\Results.csv } }
    – Chad Dye
    Commented Apr 3 at 18:10
  • The error I am getting is this: Wait-Job : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input. At line:8 char:23 + $results = $job | Wait-Job | Receive-Job + ~~~~~~~~ + CategoryInfo : InvalidArgument: ( [-r...[-k host-list]]:PSObject) [Wait-Job], ParameterBindingException
    – Chad Dye
    Commented Apr 3 at 18:12
  • Disregard. I figured it out.
    – Chad Dye
    Commented Apr 3 at 18:16
  • @ChadDye Unfortunately, Ping only outputs text, which needs to be manually split into columns (and account for error messages and such). You can use Test-Connection -Quiet instead of -AsJob to make it quite a bit faster, but it only outputs true/false for each target, so it's a bit harder to export
    – Cpt.Whale
    Commented Apr 3 at 20:14
  • I guess I will have to look into how to manually format CSVs. I've already done quite a bit of trial and error in that department myself. Do you have any resources on hand that you would recommend for this?
    – Chad Dye
    Commented Apr 3 at 21:05
0

To begin with you'll use the PowerShell native command [Test-Connection][1]. This is the PS version of the legacy ping.exe, and it is native PS and so has all the cool object features and output capabilities.

The simplest one-liner for this is:

test-connection hostname | Export-Csv path\to\csv.csv

This will run the pings against the host and record the results into the csv file specified.

You could convert your script by taking the ping line and modifying it like this:

Test-Connection $target -Count 1 | Export-CSV "c:\results\$target.csv"

This will run one ping against each target specified and record the results in its own csv file named for the target.

You can also set up an array (a variable that is a list of values) and capture each result in there and then drop it to a single output file.

2
  • I don't like test-connection for this application, mostly because it takes a long time to run for remote network objects. If your net object is more than a few hops away it takes a long time to get a return. I need constant, frequent results from each object I'm testing, so ping is the right command here. Can I just add the export chunk to the end of my ping string and have it work the same?
    – Chad Dye
    Commented Apr 3 at 17:49
  • You can test that pretty easily yourself, I think. Try "out-gridview" instead of "export-csv" to see what the ping command's output is. Commented Apr 3 at 17:52
0

It is possible to use the ping command with PowerShell to parse and format the output into a CSV file.

Every row in the CSV will represent a target, containing two columns denoting the target's name and its associated latency in milliseconds. If no response is received, the latency column will display 100% loss.

First, it'll store the ping result in a variable and apply a match operator to identify key lines (i.e. "Reply from|100% Loss"). Then, it uses split, replace, and trim logic within conditional if statements to parse and process the relevant data into the CSV out-file.

Rather than introducing additional complexity with pscustomobject in order to use export-csv, this approach maintains simplicity by using just three lines of code while retaining your existing matching logic.

PowerShell

# Define a list of IP addresses and hostnames to ping
$targets = Get-Content -Path C:\Users\Chad\Desktop\IPs.txt
$csvFile = "C:\Users\Chad\Desktop\IPs.csv"

# Loop through each target and ping it
 while (1) {
    foreach ($target in $targets) {
        $p = (ping $target -n 1) -match "Reply from|100% Loss"
        If($p -match "Reply from"){"$target,$($p.split('=')[2].replace('TTL','').Trim())" | Out-File "$csvFile" -Append}
        If($p -match "100% Loss"){"$target,100% loss" | Out-File "$csvFile" -Append} 
    } 
}

Output Example

8.8.8.8,11ms
12.34.56.78,100% loss
whoisyourmomma.com,28ms
www.cia.gov,3ms
2
  • @ChadDye .... I will add that this approach is also not "particularly elegant or groundbreaking" but it may suffice for your specific needs while allowing the use of the ping command as you desire. Commented Apr 5 at 1:58
  • Also, I used the value of target from the list being iterated in the loop to display the target being pinged. I interpreted that as the list may have IP or DNS name, so that matches what is in the target for objects that can be pinged. For the line where they are pingable, I also played with this a bit to get back the IP so if the list pings DNS name, this will show the IP rather than name defined in the list as the target If($p -match "Reply from"){"$($p.split()[2].replace(':','')),$($p.split('=')[2].replace('TTL','').Trim())"}. You can play with that in case it helps too. Commented Apr 5 at 2:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .