Search code examples
powershellpowershell-2.0powershell-3.0

Resolve-DnsName inside Test-Connection


I was wondering how I could return the Resolve-DnsName output from my Test-Connection script and add it to the CSV I created.

I like to capture the Name, Type, TTL, Section from that please.

Only invoke the Resolve-DnsName when the ping is not successful.

$servers = Get-Content "servers.txt"
$collection = $()
foreach ($server in $servers)
{
    $status = @{ "ServerName" = $server; "TimeStamp" = (Get-Date -f s) }
    $result = Test-Connection $server -Count 1 -ErrorAction SilentlyContinue
    if ($result)
    {
        $status.Results = "Up"
        $status.IP =  ($result.IPV4Address).IPAddressToString
    }
    else
    {
        $status.Results = "Down"
        $status.IP = "N/A"
        $status.DNS = if (-not(Resolve-DnsName -Name $server -ErrorAction SilentlyContinue))
        {
            Write-Output -Verbose "$server -- Not Resolving"
        }
        else
        {
            "$server resolving"
        }
    }
    New-Object -TypeName PSObject -Property $status -OutVariable serverStatus

    $collection += $serverStatus
}
$collection | Export-Csv -LiteralPath .\ServerStatus3.csv -NoTypeInformation

but nothing new is added to the CSV.


Solution

  • You ran into a PowerShell gotcha. PowerShell determines the columns displayed in tabular/CSV output from the first object processed. If that object doesn't have a property DNS that column won't be shown in the output, even if other objects in the list do have it. If other objects don't have properties that were present in the first object they will be displayed as empty values.

    Demonstration:

    PS C:\> $a = (New-Object -Type PSObject -Property @{'a'=1; 'b'=2}),
    >> (New-Object -Type PSObject -Property @{'a'=3; 'b'=4; 'c'=5}),
    >> (New-Object -Type PSObject -Property @{'b'=6; 'c'=7})
    >>
    PS C:\> $a | Format-Table -AutoSize
    
    a b
    - -
    1 2
    3 4
      6
    
    PS C:\> $a[1..2] | Format-Table -AutoSize
    
    c b a
    - - -
    5 4 3
    7 6

    If you want to generate tabular output always create your objects uniformly with the same set of properties. Choosing sensible defaults even allows you to reduce your total codebase.

    $collection = foreach ($server in $servers) {
      $status = New-Object -Type PSObject -Property @{
        'ServerName' = $server
        'TimeStamp'  = Get-Date -f s
        'Results'    = 'Down'
        'IP'         = 'N/A'
        'HasDNS'     = [bool](Resolve-DnsName -Name $server -EA SilentlyContinue)
      }
    
      $result = Test-Connection $server -Count 1 -EA SilentlyContinue
    
      if ($result) {
        $status.Results = 'Up'
        $status.IP      =  ($result.IPV4Address).IPAddressToString
      }
    
      $status
    }