1

I have the code below, to be used in Powershell; it performed well, except that I need the output file to also include the error messages whenever the IPs did not resolve to names.

Get-Content inputfile.txt | 
    foreach-object { [System.Net.Dns]::GetHostEntry($_)  } | 
    out-file -filepath outputfile.txt

At the moment, I'm able to see the red error messages displayed on Powershell window. But I want these to appear in the output file along with the results for each item listed in the input file.

Thanks in advance!

Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24
  • The exceptions produced by `GetHostEntry` don't give you a hint as to which IP failed to be resolved – Santiago Squarzon Apr 30 '22 at 23:28
  • @SantiagoSquarzon Is there a way around this? :( – fifafular92 Apr 30 '22 at 23:38
  • 1
    If a command produces errors and you want them as part of stdout, you can join errors with stdout by use `2>&1` for example `get-process 2>&1` this simply puts stderr (2) into the stdout (1) stream. This is remnant of command line. The more PowerShell way would involve using the $error variable to spit out the last error as you wish. $error has many properties that you can break apart as you want. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-error?view=powershell-7.2 ... You probably need a try catch block to ensure errors only go out when they happen. – Robert Cotterman May 01 '22 at 03:29

1 Answers1

1

Since .GetHostEntry(..) doesn't give you a clear hint as to which IP failed to be resolved it's better if you create an object that associates the IP Address you're trying to resolve with the method call. This also allows you to have a better export type, instead of plain .txt file, you can export your objects as .csv with Export-Csv.

Below example uses .GetHostEntryAsync(..) which allow us to query multiple hosts in parallel!

using namespace System.Collections.Generic
using namespace System.Collections.Specialized

(Get-Content inputfile.txt).ForEach{
    begin { $tasks = [List[OrderedDictionary]]::new() }
    process {
        $tasks.Add([ordered]@{
            Input    = $_
            Hostname = [System.Net.Dns]::GetHostEntryAsync($_)
        })
    }
    end {
        do {
            $id = [System.Threading.Tasks.Task]::WaitAny($tasks.Hostname, 200)
            if($id -eq -1) { continue }
            $thisTask = $tasks[$id]
            $thisTask['Hostname'] = try {
                $thisTask.Hostname.GetAwaiter().GetResult().HostName
            }
            catch { $_.Exception.Message }
            $tasks.RemoveAt($id)
            [pscustomobject] $thisTask
        } while($tasks)
    }
} | Export-Csv outputfile.csv -NoTypeInformation
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 2
    This is a really nice combination of PowerShell, .NET, and Async/Task +1 – Daniel May 01 '22 at 04:11
  • Thanks @Daniel, I have a similar function in [this repo](https://github.com/santysq/PowerShell-Network-Scanners) you might find them useful :) – Santiago Squarzon May 01 '22 at 04:18
  • 1
    @Santiago I have marked the answer as the solution. Thanks again. I might ask at least one more networking-related question using PowerShell in a few hours, I hope you participate again :) – fifafular92 May 01 '22 at 10:45