Search code examples
powershelldnsexport-to-csvinvokescript

Query list of computers and export DNS servers to CSV


I am trying to query a list of servers and export the DNS servers to a spreadsheet. If I run the following command against one server, I get access denied:

Get-DnsClientServerAddress -CimSession server-name -InterfaceAlias ethernet -AddressFamily IPv4 |ForEach-Object ServerAddresses
Get-DnsClientServerAddress: server-name: Cannot connect to CIM server. Access is denied.

I assume I will need to run this using Invoke-VMScript but I need help obtaining a readable CSV output. I'm looking for something like this:

SERVER NAME     DNS SERVERS
server-1        10.0.0.1
server-1        10.0.0.2
server-2        10.0.0.1

How can I query a list of computers to find their DNS servers and export them to a CSV file?

I have this code that I use for querying services but I don't know how to modify it to get DNS servers:

$user = 'domain\username'
$pwd = 'password' | ConvertTo-SecureString -Force -AsPlainText
$credential = New-Object System.Management.Automation.PsCredential($user, $pwd)

$code = @'
$obj = New-object PSObject -Property @{
  Name = 'Service does not exist'
  Status = 'Not Installed'
}
$service = Get-Service -Name SERVICE -ErrorAction SilentlyContinue
if($service)
{
  $obj.Name = $service.Name
  $obj.Status = $service.Status
}
$obj | ConvertTo-Csv
'@
Get-VM -Name (Get-Content -Path "C:\folder\server-list.txt") -PipelineVariable vm |
ForEach-Object -Process {
  $o = Invoke-VMScript -VM $vm -ScriptText $code -ScriptType Powershell -GuestCredential $credential
  $o.ScriptOutput | ConvertFrom-Csv | 
  Select-Object -Property @{N = 'VM'; E = { $vm.Name } }, Name, Status
} | Export-Csv -Path "C:\folder\server-results.csv" -NoTypeInformation -UseCulture

Solution

  • query a list of servers and export the DNS servers

    Use Invoke-Command with the -ComputerName parameter to pass the $machineList. Utilize Get-Credential to input credentials at runtime instead of embedding a password in the script. Pass the $cred to the -Credential parameter to define the security context for executing commands on the remote machines.

    Note: I'll assume you have exporting to CSV handled and any necessary service existence conditions within the script blocks covered. However, I'm happy to assist with trivial adjustments if needed.

    PowerShell - Variation 1

    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    Invoke-Command -ComputerName $machineList -ScriptBlock {Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
        Where-Object {$_.ServerAddresses.Count -ge 1} | 
            ForEach-Object {
                $serverName = $_.PSComputerName;
                $_.ServerAddresses | ForEach-Object {
                    [PSCustomObject]@{
                    'Server Name' = $serverName;
                    'DNS Server'  = $_;
                    }
                }
            };
    

    Output

    Server Name  DNS Server 
    -----------  ---------- 
    homicide002  10.105.50.15
    homicide002  10.105.51.15
    homicide002  10.105.51.10
    gangunit001  10.105.50.15
    gangunit001  10.105.51.15
    gangunit001  10.105.51.10
    

    PowerShell - Variation 2

    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    Invoke-Command -ComputerName $machineList -ScriptBlock {Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
        Where-Object {$_.ServerAddresses.Count -gt 0} | 
            Select-Object @{n="Server Name";e={$_.PSComputerName}}, @{n="DNS Server";e={$_.ServerAddresses}};
    

    Output

    Server Name  DNS Server                             
    -----------  ----------                             
    homicide002  {10.105.50.15, 10.105.51.15, 10.105.51.10}
    gangunit001  {10.105.50.15, 10.105.51.15, 10.105.51.10}
    

    PowerShell - Variation 3

    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    Invoke-Command -ComputerName $machineList -ScriptBlock {Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
        Where-Object {$_.ServerAddresses.Count -gt 0} | 
            Select-Object @{n="Server Name";e={$_.PSComputerName}}, @{n="DNS Server";e={$_.ServerAddresses.split(',') -join '; '}};
    

    Output

    Server Name  DNS Server                           
    -----------  ----------                           
    homicide002  10.105.50.15; 10.105.51.15; 10.105.51.10
    gangunit001  10.105.50.15; 10.105.51.15; 10.105.51.10
    

    PowerShell - Variation 4

    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    Invoke-Command -ComputerName $machineList -ScriptBlock {Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
        Where-Object {$_.ServerAddresses.Count -gt 0} | 
            Select-Object @{n="Server Name";e={$_.PSComputerName}}, @{n="DNS Server";e={$_.ServerAddresses.split(',') -join ', '}};
    

    Output

    Server Name  DNS Server                           
    -----------  ----------                           
    homicide002  10.105.50.15, 10.105.51.15, 10.105.51.10
    gangunit001  10.105.50.15, 10.105.51.15, 10.105.51.10
    

    PowerShell - Variation 5 (with unavailable)

    $ErrorActionPreference = "stop";
    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    foreach ($machine in $machineList) {
        try {
            $dnsResults = Invoke-Command -ComputerName $machine -ScriptBlock {
                Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
                    Where-Object {$_.ServerAddresses.Count -ge 1} | 
                        ForEach-Object {
                            $serverName = $_.PSComputerName
                            $_.ServerAddresses | ForEach-Object {
                                [PSCustomObject]@{
                                    'Server Name' = $serverName
                                    'DNS Server'  = $_
                                }
                            }
                        }
            if($dnsResults) {$dnsResults | Select-Object -Unique 'Server Name', 'DNS Server'}
        } catch {
            [PSCustomObject]@{
                'Server Name' = $machine
                'DNS Server'  = 'Unavailable'
            }
        }
    };
    

    PowerShell - Variation 6 (with unavailable)

    $ErrorActionPreference="stop";
    $cred = Get-Credential "domain\username";
    $machineList = Get-Content -Path "C:\folder\server-list.txt";
    
    foreach ($machine in $machineList) {
        Try { Invoke-Command -ComputerName $machine -ScriptBlock {
                Get-DnsClientServerAddress -AddressFamily IPv4} -Credential $cred | 
                    Where-Object {$_.ServerAddresses.Count -gt 0} | 
                        Select-Object -Unique @{n="Server Name";e={$_.PSComputerName}}, 
                                              @{n="DNS Server";e={$_.ServerAddresses.split(',') -join ', '}};
        } Catch {
            [PSCustomObject]@{
            'Server Name' = $machine
            'DNS Server'  = 'Unavailable'
            }
        }
    };