Harry Singh
Harry Singh

Reputation: 423

Ping a list of host names and output the results to a csv in powershell

I have a large list of hostnames I need to ping to see if they are up or down. I'm not really that great at scripting but I managed to figure this much out:

$names = Get-content "hnames.txt"

foreach ($name in $names){
  if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
    Write-Host "$name is up" -ForegroundColor Green
  }
  else{
    Write-Host "$name is down" -ForegroundColor Red
  }
}

This gets me what I need but i now need to write out these results to a csv file and i have no idea how to do that.

Please Help!

Upvotes: 8

Views: 156009

Answers (5)

William Wilkins
William Wilkins

Reputation: 23

So I modified @js2010 answer to check a list of ports and the ICMP ping, set the status if either the ports or the ICMP ping came back. Also set it to run by just executing instead of passing a file on execution.

function get-pport {

    # Define the file path containing the URLs
    $urlFile = "hnames.txt"
    $outputFile = "port_scan_results.csv"
    
    # Define the list of ports
    $ports = @(22, 443, 80)

    # Read URLs from the file
    $urls = Get-Content $urlFile
    
    $results = @()

    $urls | ForEach-Object {
        $url = $_
        $openPorts = @()

        # Perform ICMP ping
        try {
            $ping = New-Object System.Net.NetworkInformation.Ping
            $pingResult = $ping.Send($url)

            if ($pingResult.Status -eq 'Success') {
                $status = "up"
            } else {
                $status = "down"
            }
        } catch {
            Write-Host "Error: ICMP ping failed for $url - $_"
            $status = "down"
        }

        # Check for open ports
        foreach ($port in $ports) {
            $client = New-Object System.Net.Sockets.TcpClient
            $ar = $client.BeginConnect($url, $port, $null, $null)
            $wait = $ar.AsyncWaitHandle.WaitOne(200, $false)

            if ($wait -and !$ar.IsCompleted) {
                $client.Close()
            }
            else {
                if ($client.Connected) {
                    $openPorts += $port
                }
                $client.Close()
            }
        }

        if ($openPorts -and $status -eq "down") {
            $status = "up"
        }

        $result = New-Object -TypeName PSObject -Property @{
            HostName = $url
            Port = $openPorts -join ','
            Status = $status
        }

        $results += $result
    }

    # Export results to CSV
    $results | Export-Csv -Path $outputFile -NoTypeInformation
}

# Run the function
get-pport

Upvotes: 0

js2010
js2010

Reputation: 27433

I would do it this way. Using a list of computers and -asjob works very well. The Responsetime property (confusingly the header is "Time(ms)") will be non-null if the host is up.

$names = Get-content hnames.txt
test-connection $names -asjob -count 1 | receive-job -wait -auto
Source        Destination     IPV4Address      IPV6Address     Bytes    Time(ms)
------        -----------     -----------      -----------     -----    --------
COMP001       yahoo.com       74.6.231.21                      32       39
COMP001       microsoft.com   40.113.200.201                   32

Lately I do it this way. It requires threadjobs installed in powershell 5.1. Or just use get-port. I stick it in a mymod\mymod.psm1 module file somewhere in $env:psmodulepath. I can check a classroom in under 10 seconds.

function get-pport {  # multi-threaded
  param($list)
  
  $list |
    % { $_ | start-threadjob { get-port $input } -throttlelimit 20 } |
    receive-job -wait -auto
}

function Get-Port {

  Param (
    [parameter(ValueFromPipeline)]
    [string[]]$Hostname='yahoo.com'
  )
  
  begin {   
    $ports = 22,5988,3389,5985
    $ping = New-Object System.Net.Networkinformation.ping
    $Timeout = 200 # ms 
  }

  process {
    $hostname | foreach {
      $openPorts = @()
  
      foreach ($port in $ports) {
        $client = New-Object System.Net.Sockets.TcpClient
        $beginConnect = $client.BeginConnect($_,$port,$null,$null)
        Start-Sleep -Milli $TimeOut
        if($client.Connected) { $openPorts += $port }
        $client.Close()
      }
  
      $result = $Ping.Send($_, $timeout)
      if (! $result) { write-error "hostname $_ not found" }
      $pingstatus = ($result.status -eq 'Success')
  
      New-Object -typename PSObject -Property @{
        HostName = $_
        Port = $openPorts
        Ping = $pingstatus 
      } | select hostname,port,ping
    } # end foreach
  } # end process

}

Example:

$avid = cat afile.txt
pport $avid

HostName Port          Ping
-------- ----          ----
A006     {3389, 5985}  True
A011     {3389, 5985}  True
A015     {3389}        True

Upvotes: 1

Patrick Burwell
Patrick Burwell

Reputation: 173

    $Output= @()
    $names = Get-Content ".\input\Servers.txt"
    foreach ($name in $names){
      if (Test-Connection -Delay 15 -ComputerName $name -Count 1 -ErrorAction SilentlyContinue -quiet){
       $Output+= "$name,up"
       Write-Host "$Name,up" -ForegroundColor Green
      }
      else{
        $Output+= "$name,down"
        Write-Host "$Name,down" -ForegroundColor Red
      }
    }
    $Output | Out-file ".\output\result.csv"

This is a tad cleaner, and includes the original foreground options but, BTW, the 'delay' switch seems to be ignored -PB

Upvotes: 0

Mitch
Mitch

Reputation: 41

I am a complete newbie to Powershell, so I took this on as a learning task, as I needed a quick and simple way to check a list of PC's for up/down status. These tweaks were needed to get it to output cleanly to the screen and to a txt file

$Output= @()
$names = Get-content "hnames.txt"
foreach ($name in $names){
  if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
   $Output+= "$name,up"
   Write-Host "$Name,up"
  }
  else{
    $Output+= "$name,down"
    Write-Host "$Name,down"
  }
}
$Output | Out-file "C:\support\result.csv"

Upvotes: 4

Erez breiman
Erez breiman

Reputation: 486

You can use the following code instead (I simply altered the write-host calls to CSV formatting) and execute it with "PowerShell.exe script.ps > output.csv" Note that you must execute it from the folder that contains hnames.txt, or simply change the "hnames.txt" to a full path.

$names = Get-content "hnames.txt"

foreach ($name in $names){
  if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
    Write-Host "$name,up"
  }
  else{
    Write-Host "$name,down"
  }
}

P.S. You can also use the Out-File Cmdlet to create the CSV file

Upvotes: 16

Related Questions