0

My code:

$Servers = Get-Content -Path "./FULl_List_hosts_all_CSV_V2.txt"
$Array = foreach($Server in $Servers) {
    $Server = $Server.Trim()
    try {
        $DNSCheck = [System.Net.Dns]::GetHostEntry($Server)
        # just output an object so it gets collected in variable $Array
        [PsCustomObject]@{ 
            'Server name' = $Server  # or $DNSCheck.HostName
            'IP Address'  = ($DNSCheck.AddressList | Where-Object {$_.AddressFamily -eq 'InterNetwork'})[0].IPAddressToString
        }
    }
    catch {
        # either do nothing here to skip this server of output a 'n/a' object
        [PsCustomObject]@{ 
            'Server name' = $Server
            'IP Address'  = 'n/a'
        }
    }
}

# output on screen
$Array | Format-Table -AutoSize

# write to csv
$Array | Export-Csv -Path "./pingstatus.csv" -NoTypeInformation 

The Full_List_Hosts has more than 150K hostnames. When I run the shell script it sits there. No doubt loading it all - but is there a way I can make it count up to maybe 200 then pause, write to the csv file then continue? If I do a shorter file - the script takes seconds to complete. Just want to make sure it is truly running. OPen to recomendations. thanks

I tried using a shorter list of hosts in a file. worked fine. I want some indicaton that it is running and not just sitting there with a "dumb look" only to come after HOURS of running and find nothing.

Marc
  • 1
  • 1
    How about using a progress bar inside your loop? `¯\_(ツ)_/¯` – Olaf Jul 17 '23 at 08:41
  • 1
    Have a look at `Write-Progress`. – zett42 Jul 17 '23 at 08:42
  • Your code would benefit a lot from multithreading, `[System.Net.Dns]::GetHostEntry(...)` is slowing you down. If you have pwsh 7+ you can use `ForEcach-Object -Parallel` then pipe directly the output to `Export-Csv` – Santiago Squarzon Jul 17 '23 at 12:27

2 Answers2

1

Just use the PowerShell pipeline the way it is designed:

Get-Content -Path "./FULl_List_hosts_all_CSV_V2.txt" | Foreach-Object {
    $Server = $_.Trim()
    $Output = try {
        $DNSCheck = [System.Net.Dns]::GetHostEntry($Server)
        # just output an object so it gets collected in variable $Array
        [PsCustomObject]@{ 
            'Server name' = $Server  # or $DNSCheck.HostName
            'IP Address'  = ($DNSCheck.AddressList | Where-Object {$_.AddressFamily -eq 'InterNetwork'})[0].IPAddressToString
        }
    }
    catch {
        # either do nothing here to skip this server of output a 'n/a' object
        [PsCustomObject]@{ 
            'Server name' = $Server
            'IP Address'  = 'n/a'
        }
    }
    $Output | Format-Table -AutoSize | Out-Host
    $Output
} | Export-Csv -Path "./pingstatus.csv" -NoTypeInformation 

A more advanced solution (that also supports batches) would be using the steppable pipeline, see e.g.: Trouble Splitting a 9 GB csv file via Powershell

iRon
  • 20,463
  • 10
  • 53
  • 79
  • 1
    It looks like pipelines are as fast as ReadLines. I didn't realize that. I'll make a note of it. Thanks. – Atercat Jul 17 '23 at 09:39
-1

You can process the file line by line. It will be much faster. And the result of each server check will be visible immediately.

foreach($server in [System.IO.File]::ReadLines("C:\path\to\FULl_List_hosts_all_CSV_V2.txt"))
{
   ...
   $result = [PsCustomObject]@{ ... }
   Write-Output $result
   $result | Export-Csv -Path "./pingstatus.csv" -NoTypeInformation -Append
}
Atercat
  • 99
  • 5
  • 1
    [Wrapping the `Export-Csv ` cmdlet is quiet expensive](https://learn.microsoft.com/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations#avoid-wrapping-cmdlet-pipelines) for a 150K job, and therefore should go outside the loop. – iRon Jul 17 '23 at 09:20