PS1 Array DNS Query Better Layout Help

I created a basic script but would like to create something a little better and need a little help. Not a wizard at scripting but trying to work better at it.

I create a csv file ipaddress,hostname. and import-csv. inside the script I create a variable with the list of dns servers to query. If query works PASS will be placed and if failed FAIL is placed. Would like the output to look like this in the output csv file. (ipaddress,hostname,dns1,dns2,dns3,dns4,dns5) ex. (192.168.1.1,Happy,PASS,PASS,FAIL,PASS,PASS) Once in this format can put color to pass and fail inside excel.

This is what I currently have but not really seeing how to make it play to what I would like. I know its terrible I’m trying.

$ipFile = Get-Content c:\temp\dnsQuery\ipaddress.txt
$hostFile = Get-Content c:\temp\dnsQuery\names.txt

foreach ($ip in $ipFile) {
foreach ($dns in $dnsServer){
try{
Resolve-DnsName $ip -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
$dnsRecord = Resolve-DnsName $ip -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
Write-Output “$ip $dns PASS $dnsRecord” | Out-File $ipv4RevPath -Append
}
catch{

    Write-Output "$ip $dns FAIL" | Out-File $ipv4RevPath


}

}
}

foreach ($hname in $hostFile) {
foreach ($dns in $dnsServer){
try{
Resolve-DnsName $hname -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
$dnsRecord = Resolve-DnsName $hname -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
Write-Output “$ip $dns PASS $dnsRecord” | Out-File $ipv4FwdPath -Append
}
catch{
Write-Output “$hname $dns FAIL” | Out-File $ipv4FwdPath

}
}
}

Captain,
Welcome to the forum. :wave:t4:

Before we start … when you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.
Thanks in advance

I’m confused - you have two independend loops and in booth loops you’re using a variable $dnsServer. But I don’t see where you define it.
Then - if you want to have the output as CSV file you should use Export-Csv - it is made for.
Then - in both loops you use the same query twice. But once even without saving the output to a variable. So you actually only waste time and cpu cycles with this command. :wink:

You may share a sample of your input files as well (formatted as code). This way we may be able help you better.

Sorry about that. I am not a coder normally but this task has driven me to start to become one. I will post my full code below. I have 2 files one with hostname and one with IPAddress. I would like to have a csv file with the IPAddress and hostname so that I can verify them side by side to reduce errors. Pulling out the data from the Import-Csv was a little tricky but figured out that I needed to add the descriptor in the call out. $d[0].ipaddress or $d[1].hostname.

I have that same loop but with different variables and files. If I can run it once for each line in csv file and place the data as correctly that would be awesome. Need to run all test from and place FAIL or PASS in correct location. But I am not seeing how to Print PASS in a field beside add to variable for array. $ip_array = @(0,1,2,3,4,5,6). then host_array = @(0,1,2,3,4,5). Can I then push the arrays into a line of the file like my -APPEND?

Write-Output " $ip_arrary[0],host_arrary[0],ip_arrary[1],host_arrary[1],ip_arrary[2],host_arrary[2],…etc" | Out-File $singleCsvFIle.csv -Append

Goal is to test 6 internal DNS servers with local hostnames. Using public as a test for my script.

Other single files are single lines with ip or hostnames as in this csv below.

CSV file created.

ipaddress domain
34.212.84.191 whatisthematrix.com
104.200.23.95 cbtnugget.com
# DNS SERVER : MULTIPLE SERVERS FOR TESTING : DNS SERVERS
$dnsServer = @('8.8.8.8','8.8.4.4','206.67.222.222','206.67.220.220')


# INPUT FILES : FILES TO BE REQUESTED : INPUT FILES
$hostFile = Get-Content c:\temp\dnsQuery\names.txt
$ipFile = Get-Content c:\temp\dnsQuery\ipaddress.txt
#$dnsServerFile = Get-Content c:\temp\dnsQuery\dnsServers.txt


# CREATION : DIRECTORY - FOLDER - FILES : CREATION

$startDate = (Get-Date).ToString("yyy-MM-dd_hh-mm-ss")

$folderName = ($startDate)
New-Item -itemType Directory -Path C:\temp\dnsQuery\ -Name $folderName

$dirPath = "c:\temp\dnsQuery\$folderName\"

$ipv4Reverse = ($startDate + "_00_reverse_lookup.txt")
New-Item -itemType File -Path ($dirpath + $ipv4Reverse)
$ipv4ReversePath = ($dirPath + $ipv4Reverse)

$hostFoward = ($startDate + "_00_foward_lookup.txt")
New-Item -itemType File -Path ($dirpath + $hostFoward)
$hostFowardPath = ($dirPath + $hostFoward)



# TEST 1 : VERIFY IPv4 REVERSE LOOKUP : TEST 1

foreach ($ip in $ipFile) {
        foreach ($dns in $dnsServer){
    try{
        Resolve-DnsName $ip -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
        $dnsRecord = Resolve-DnsName $ip -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
        Write-Output "$ip   $dns    PASS $dnsRecord" | Out-File $ipv4ReversePath -Append
    }
    catch{

        Write-Output "$ip $dns FAIL" | Out-File $ipv4ReversePath -Append

    }
 }
}

# TEST 2 : VERIFY HOSTNAME FOWARD LOOKUP : TEST 2

foreach ($hname in $hostFile) {
    foreach ($dns in $dnsServer){
try{
    Resolve-DnsName $hname -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
    $dnsRecord = Resolve-DnsName $hname -Server $dns -ErrorAction Stop | Select Name,IPAddress,NameHost,Type
    Write-Output "$hname   $dns    PASS $dnsRecord" | Out-File $hostFowardPath -Append
}
catch{

    Write-Output "$hname $dns FAIL" | Out-File $hostFowardPath -Append

   }
 }
}

`
type or paste code here
```

Good for you. Your life starts to become easier. :+1:t4: :slightly_smiling_face:

I’m even more confused. :thinking: :crazy_face:

To make things a little easier I’ll focus on one of your tasks - the check of the forward lookup test.

$dnsServerList = @('8.8.8.8', '8.8.4.4')
$hostNameList = Get-Content -Path 'c:\temp\dnsQuery\names.txt'

$TimeStamp = Get-Date
$OutputPath = Join-Path -Path 'C:\temp\dnsQuery' -ChildPath $($TimeStamp.ToString('yyy-MM-dd_hh-mm-ss'))
if (-not (Test-Path -Path $OutputPath)) {
    New-Item -Path $OutputPath -ItemType Directory | Out-Null
}
$ForwardLookupFileName = "ForwardLookupResults_$($TimeStamp.ToString('yyy-MM-dd_hh-mm-ss')).csv"
$ForwardLookupResults = Join-Path -Path $OutputPath -ChildPath $ForwardLookupFileName

$ResultList = 
foreach ($hostName in $hostNameList) {
    foreach ($dnsServer in $dnsServerList) {
        try {
            $dnsRecordList = Resolve-DnsName -Name $hostName -Server $dnsServer -ErrorAction Stop
            foreach ($dnsRecord in $dnsRecordList) {
                [PSCustomObject]@{
                    InputHostName = $hostName
                    DNSServer     = $dnsServer
                    Name          = $dnsRecord.Name
                    Type          = $dnsRecord.Type
                    TTL           = $dnsRecord.TTL
                    Section       = $dnsRecord.Section
                    IPAddress     = $dnsRecord.IPAddress
                }
            }
        }
        catch {
            foreach ($dnsRecord in $dnsRecordList) {
                [PSCustomObject]@{
                    InputHostName = $hostName
                    DNSServer     = $dnsServer
                    Name          = 'n/a'
                    Type          = 'n/a'
                    TTL           = 'n/a'
                    Section       = 'n/a'
                    IPAddress     = 'n/a'
                }
            }
        }
    }
}

$ResultList |
Export-Csv -Path $ForwardLookupResults -NoTypeInformation

I don’t know why someone would need to check something like this but if you have pairs of hostnames and according ip addresses you should provide them as pairs with a CSV file and check them together. This way you wouldn’t need to compare them afterwards. The result would be contained in the data you receive from your code.

BTW: If you want to import the data into Excel later on anyway you may take a look at the great module from Doug Finke

I need to know because someone else is adding the information into DNS and it’s either not being entered correctly or some are missing. I have a list of over 600 ip to hostnames that need verified before I can move forward with part of the project. I have been checking them one by one off an excel sheet and been hell. So why not take the opportunity to learn a little coding I thought. How bad could it be. lol

By the way. Yours looks so much better then the crap I created. Thank you will try it tomorrow and try to better my knowledge by your example.

That’s waht I meant. Simply export them to a CSV file and use this as input for your script. This way the result wouldn’t be two separate unrelated lists - it would be one containing all you need.

That works beautifully. I did add after DNSServer a results field ‘PASS’ & ‘FAIL’ inside excel I can add Conditional Formatting Green and Red to show off details at a glance.

Couple questions.
$ResultList = is alway accepting, so -Append is not needed correct? That removes the part Write-Output.

Removing the Single Text File, names.txt and replacing it was dnsQueryList.csv with headers named and address. How do I call that out in the script? These are my thoughts.

Address	Hostname
10.10.220.100	server01
10.10.220.101	server02
10.10.220.102	server03
10.10.220.103	server04


$ResultList = 
foreach ($hostName in $hostNameList) {
    foreach ($dnsServer in $dnsServerList) {
        try {
            $dnsRecordList = Resolve-DnsName -Name $hostName -Server $dnsServer -ErrorAction Stop
            foreach ($dnsRecord in $dnsRecordList) {
                [PSCustomObject]@{
                    InputHostName = $hostName
                    DNSServer     = $dnsServer
                    Result        = 'PASS'
                    Name          = $dnsRecord.Name
                    Type          = $dnsRecord.Type
                    TTL           = $dnsRecord.TTL
                    Section       = $dnsRecord.Section
                    IPAddress     = $dnsRecord.IPAddress
                    SPACE        = null
                    Inputaddress = $address
                    DNSServer     = $dnsServer
                    Result        = 'PASS'
                    Name          = $dnsRecord.Name
                    Type          = $dnsRecord.Type
                    TTL           = $dnsRecord.TTL
                    Section       = $dnsRecord.Section
                    IPAddress     = $dnsRecord.IPAddress```

Note: Forward lookup is looking up by hostname server1. Reverse Lookup is by the IPAddress. Only note because I just had a conversation with 10 people who had no idea what they were and why it was so important.

dns.google = forward lookup - used with DNS like looking phone book or calling name from phone contacts, like MOM.
8.8.8.8 = reverse lookup - dial MOM phone number because you know it and cutting out the phone book.

Like to have the output go across the sheet so I can ref the Hostname and IPAddress and which DNS Server Pass or Failed on Forward Lookup and Reverse Lookup.

Input HostName	DNSServer	Result	Name	Type	TTL	Section IPAaddress	(SPACE)	Input Address	DNSServer	Result	NameHost	Type	TTL	Section IPAaddress

In doing that would I create another?

$dnsQuery = Import-Csv -Path 'c:\temp\dnsQuery\dnsQueryList.csv'
$addressList = $dnsQuery[0].Address
$hostNameList = $dnsQuery[0].Hostname

foreach ($address in $addressList)  put everything inside that and add another $addressDnsRecordList = Resolve-DnsName -Name $address -Server $dnsServer - ErrorAction Stop

Not sure if thats the correct way to add the [0].address column to look at?

Hmmm … I think you’re overcomplicating this. Anyway, I will give you my 2 ¢. :wink:

I just see that you added 'PASS' - maybe you added 'FAIL' in a part you didn’t share. Anyway, I think that’s unnecessary. Since you’d have at least something in the columns when you get an answer from the DNS server you could add an Excel filter to that cell. When there’s no answer from the DNS server you’d output a self made string anyway. So you wouldn’t need an extra column. I would even omit columns I don’t need at all. If you don’t need the TTL or Type column just omit it.

And - regardless of that - when I got it right you want to place the result of the forward and the reverse test in one line. I’d think that’s a bad idea because at least the forward test can return more than one result.
If you want to do it anyway you have to do both tests inside one loop and you have to deal with cases where you have more than one result from one of the tests.

Hmmm … yes and no.

If you use a proper/valid CSV file you can easily access the single values with the dot notation … like this:

$CSVInputData =
@'
Address	Hostname
10.10.220.100	server01
10.10.220.101	server02
10.10.220.102	server03
10.10.220.103	server04
'@ | 
    ConvertFrom-Csv -Delimiter "`t"

foreach ($line in $CSVInputData) {
    'IPAddress: {0} - ServerName: {1}' -f $line.Address, $line.Hostname
}

You don’t need to loop them separately.

You are like a God at this. Clearly I am not a programer. Been beating me head trying to manipulate all these lines testing and here you are with its a couple lined done. HAHA

I’m just doing this much longer than you.

Additional thought … depending on your actual goal comparing DNS server records you could actually do this comparison or check in PowerShell code inside the loop and only output the non-compliant records. :wink:

I could. I can filter inside Excel. Been working on a loop test to check the IPADDR from the query and from the csv file to verify they are correct and Print out PASS or FAIL in the field but keep scraping it from failing. Like to do the reverse lookup to compare hostname as well, but that would be a 2 test because sometime there are only hostnames or FQDN or via versa. Well might want both field so I know what’s reported.

This started out as a simple tool to test and now I want this as a tool I use at any DNS problems.

What is the -f doing? Not finding that option

https://www.google.com/search?q=Powershell+"-f"

:wink:

I don’t know how often you have to do that but it might be worth the effort to atomate the comparison as much as possible.

That might be unnecessary then.

That’s what I meant - why outputting the ones with the status PASS? They are compliant/fine/ok. No need to look at. No need need to put more effort to them. :wink:

If it saves you from a lot of boring and repetetive work and saves you a lot of time you can spend for more interesting things it should be worth it I think.

In all honesty, I don’t like DNS much. Seems to be problems after people change records. Have this script would help validate everything is working or not. I call everything out in my environments by IP address because its 100% working or not and no other services are reliant on it.

Having the PASS or FAIL helps show me what working and if someone is questioning a server it is there to show. Plus like having it to show that these servers are working and this one is being a turd. I debated on having results for that reason, but I can show them the results for everything quickly. One less test I have to run. I go inside Excel and make it with a green background and white letters. Fail is red background with white letters. If I could automate that with the script life would be perfect HAHA.

Thinking about it. The plan will be to have the Full DNS records in the dnsQuery.csv. When I get a call about the network down think its DNS, I can do a few test for DNS and can run the full DNS scan to verify. Find the host and have a quick see. Plus can verify its working like should.

I have a manipulation question.

Reverse Lookup / Pointer Record looks like 11.1.168.192.in-addr.arpa. When I run the test my IP address = 192.168.1.11. $line.Address = 192.168.1.11

How can I pull the 11.1.168.192 out and reverse it to 192.168.1.11 so I can run an if test.

I was thinking putting in an array then taking the places out.
11.1.168.192.in-addr.arpa
[0].[1].[2].[3].[4].[5]. then reorder as $newOrder= ([3].[2].[1].[0])

But cant get it to work. Am I far off?

if ($line.Address -eq $newOrder) {
                         $RvDnsCheck = 'PASS'
                     }
                     else {
                         $RvDnsCheck = 'FAIL'
                    }

Nope, you’re nearly there:

PS E:\Temp> '11.1.168.192.in-addr.arpa'.Split('.')[3,2,1,0] -join '.'
192.168.1.11
2 Likes

Hmmm … ok, Matt already told you how to do … but whatfor actually? You still have to query regular ip addresses or names!?! The only thing what’s reversed actually are zone names for the reverse lookup zones. And to get those you simply use

 Get-DnsServerZone -ComputerName 'ServerName'  | 
    Where-Object -Property 'IsReverseLookupZone' -EQ -Value $true
2 Likes

Nice. Another couple of ways using [array]::Reverse()

$record = '11.1.168.192.in-addr.arpa'


$numbers = [regex]::Matches($record,'\d+').value
[array]::Reverse($numbers)
$numbers -join '.'

$numbers = $record.split('.') -match '\d+'
[array]::Reverse($numbers)
$numbers -join '.'
2 Likes

Sorry been busy with the broken DNS. I have been checking back and forth to make sure the correct FQDN and Reverse addresses are configure. Seem the Reverse was not correct and causing some issues. They had a script push out the updates and it went squirrelly. Some of the names were not match appropriately to the FQDN or IPADDRs.

Looking at the data looked fine but once I did the check on reverse some of the 1 were I and some 0 were O. Depending on the font we didnt pick it up. Why there were letters, Im not sure. I can understand on the BIND servers maybe but on the Windows DNS, not sure how it was accepted.