PowerShell diagnostic script for investigating DNS issues on an AD-integrated DNS server

PowerShell investigation script: Investigate-ADDNS.ps1

What the script does

This script performs a comprehensive health check on a Windows Server that hosts both Active Directory Domain Services (AD DS) and DNS Server. It is designed to run directly on the target server as an Administrator.

Here is a summary of the checks it performs:

  1. Role & Service Validation
    • Confirms the DNS Server service is installed, running, and set to automatic start.
    • Confirms the server is recognized as a Domain Controller.
    • Checks that AD Web Services (ADWS) is running.
  2. DNS Server Configuration
    • Lists the IP addresses the DNS server is listening on.
    • Checks if DNS forwarders are configured.
    • Verifies that root hints are present.
  3. DNS Zones
    • Enumerates forward and reverse lookup zones.
    • Checks whether zones are Active Directory-integrated.
    • Checks if aging and scavenging are enabled (to prevent stale record buildup).
  4. Critical AD DNS Records
    • Resolves NS records for the domain.
    • Resolves essential SRV records (_ldap, _kerberos, _ldap._tcp.dc._msdcs, GC records).
    • Verifies the DC’s own A record resolves correctly.
    • Provides advice to run ipconfig /registerdns and restart Netlogon if records are missing.
  5. DNS Client Settings
    • Checks the network adapter DNS settings.
    • Warns if 127.0.0.1 is missing or if the DNS configuration looks incorrect for a DC.
  6. Resolution & Connectivity
    • Tests external name resolution (e.g., Google, Microsoft) to verify forwarders/root hints work.
    • Tests if TCP port 53 is responding locally.
  7. AD Replication
    • Checks replication partner metadata. Since AD-integrated DNS stores data in AD, replication health directly impacts DNS consistency.
    • Optionally runs repadmin /showrepl if available.
  8. DCDiag (Optional)
    • If you use the -IncludeDCDiag switch, it runs targeted dcdiag tests for DNS, registration, and advertising.
  9. Event Logs (Optional)
    • If you use the -IncludeEventLogs switch, it scans the DNS Server and Directory Service event logs for errors and critical events within the last day (configurable).
  10. Remediation Advice
    • At the end, it analyzes the results and prints specific PowerShell or command-line remediation suggestions based on what failed.

How to run it

Open an elevated PowerShell window on the DC/DNS server and run:

powershell

# Basic investigation
.\Investigate-ADDNS.ps1

# Include DCDiag and Event Log checks
.\Investigate-ADDNS.ps1 -IncludeDCDiag -IncludeEventLogs

# Custom log/report paths
.\Investigate-ADDNS.ps1 -LogPath "C:\Logs\DNS_Check.log" -ReportPath "C:\Logs\DNS_Check.csv"

Output

  • Console output: Color-coded status messages and a summary table.
  • Log file: A timestamped .log file with all details.
  • CSV report: A structured .csv file you can open in Excel for review or documentation.

Powershell Script (Investigate-ADDNS.ps1) Below

<#
.SYNOPSIS
AD DNS Health Investigation Script
.DESCRIPTION
Performs comprehensive diagnostic checks on a Windows Server running AD DS and DNS
to identify common DNS configuration, replication, and resolution issues.
.NOTES
Run as Administrator / Domain Admin on the target DC/DNS server.
Requires RSAT-DNS-Server tools on some checks if run remotely.
#>

[CmdletBinding()]
param(
[string]$LogPath = “C:\Temp\ADDNS_Investigation_$(Get-Date -Format ‘yyyyMMdd_HHmmss’).log”,
[string]$ReportPath = “C:\Temp\ADDNS_Investigation_$(Get-Date -Format ‘yyyyMMdd_HHmmss’).csv”,
[switch]$IncludeEventLogs,
[switch]$IncludeDCDiag,
[int]$EventLogDays = 1
)

#Requires -RunAsAdministrator

#region Helper Functions
function Write-Log {
param([string]$Message, [ValidateSet(‘Info’,’Warning’,’Error’,’Success’)][string]$Level = ‘Info’)
$ts = Get-Date -Format “yyyy-MM-dd HH:mm:ss”
$line = “[$ts] [$Level] $Message”
switch ($Level) {
‘Warning’ { Write-Host $line -ForegroundColor Yellow }
‘Error’ { Write-Host $line -ForegroundColor Red }
‘Success’ { Write-Host $line -ForegroundColor Green }
default { Write-Host $line -ForegroundColor Cyan }
}
$line | Out-File -FilePath $LogPath -Append -Encoding UTF8 -ErrorAction SilentlyContinue
}

function Test-IsDomainController {
try {
$role = (Get-ItemProperty “HKLM:\SYSTEM\CurrentControlSet\Control\ProductOptions” -Name ProductType).ProductType
return ($role -eq “LanmanNT”)
} catch { return $false }
}

function Add-Result {
param([string]$Category,[string]$Test,[string]$Result,[string]$Details)
$script:Results += [PSCustomObject]@{
Timestamp = Get-Date -Format “yyyy-MM-dd HH:mm:ss”
Category = $Category
Test = $Test
Result = $Result
Details = $Details
}
}

$script:Results = @()
#endregion

#region Initialization
$Host.UI.RawUI.WindowTitle = “AD DNS Health Investigation”
if (-not (Test-Path (Split-Path $LogPath))) { New-Item -ItemType Directory -Path (Split-Path $LogPath) -Force | Out-Null }
Write-Log “========== AD DNS Investigation Started ==========”
Write-Log “Server: $env:COMPUTERNAME”
Write-Log “User: $env:USERDOMAIN$env:USERNAME”
Write-Log “Log file: $LogPath”
#endregion

#region 1. Basic Server & Role Validation
Write-Log “— Checking Server Roles and Prerequisites —“

$dnsService = Get-Service -Name DNS -ErrorAction SilentlyContinue
if ($dnsService) {
$status = $dnsService.Status
$startType = (Get-WmiObject Win32_Service -Filter “Name=’DNS'”).StartMode
Write-Log “DNS Service Status: $status (StartType: $startType)”
if ($status -eq ‘Running’) {
Add-Result -Category “Services” -Test “DNS Service” -Result “PASS” -Details “DNS service is running (Start: $startType)”
} else {
Add-Result -Category “Services” -Test “DNS Service” -Result “FAIL” -Details “DNS service is NOT running. Status: $status, StartType: $startType”
}
} else {
Write-Log “DNS Server role does not appear to be installed.” “Error”
Add-Result -Category “Services” -Test “DNS Service” -Result “FAIL” -Details “DNS service not found”
}

$isDC = Test-IsDomainController
Write-Log “Is Domain Controller: $isDC”
Add-Result -Category “Server” -Test “DC Role Check” -Result $(if($isDC){“PASS”}else{“WARNING”}) -Details “ProductType indicates DC status: $isDC”

try {
$adws = Get-Service -Name ADWS -ErrorAction Stop
Write-Log “AD Web Services: $($adws.Status)”
Add-Result -Category “Services” -Test “ADWS” -Result $(if($adws.Status -eq ‘Running’){“PASS”}else{“FAIL”}) -Details “Status: $($adws.Status)”
} catch {
Write-Log “AD Web Services not found.” “Warning”
Add-Result -Category “Services” -Test “ADWS” -Result “FAIL” -Details “ADWS service not found”
}
#endregion

#region 2. DNS Server Configuration
Write-Log “— Investigating DNS Server Configuration —“

try {
$dnsServer = Get-DnsServer -ErrorAction Stop
Write-Log “DNS Server ComputerName: $($dnsServer.ComputerName)”
Write-Log “Listening IP Addresses: $($dnsServer.ListeningIPAddress -join ‘, ‘)”
Write-Log “Forwarders: $((Get-DnsServerForwarder).IPAddress.IPAddress -join ‘, ‘)”

$forwarders = Get-DnsServerForwarder
if ($forwarders.IPAddress) {
    Add-Result -Category "DNS Config" -Test "Forwarders Configured" -Result "INFO" -Details "Forwarders: $($forwarders.IPAddress.IPAddress -join ', ')"
} else {
    Add-Result -Category "DNS Config" -Test "Forwarders Configured" -Result "WARNING" -Details "No DNS forwarders configured. Root hints will be used."
}

if ($dnsServer.ListeningIPAddress.Count -eq 0) {
    Add-Result -Category "DNS Config" -Test "Listening IPs" -Result "FAIL" -Details "DNS server is not listening on any IP addresses."
} else {
    Add-Result -Category "DNS Config" -Test "Listening IPs" -Result "PASS" -Details "Listening on: $($dnsServer.ListeningIPAddress -join ', ')"
}

# Root hints check
$rootHints = Get-DnsServerRootHint
if ($rootHints.Count -eq 0) {
    Add-Result -Category "DNS Config" -Test "Root Hints" -Result "FAIL" -Details "No root hints configured."
} else {
    Add-Result -Category "DNS Config" -Test "Root Hints" -Result "PASS" -Details "$($rootHints.Count) root hints present."
}

} catch {
Write-Log “Failed to retrieve DNS server configuration: $” “Error”
Add-Result -Category “DNS Config” -Test “DNS Config Retrieval” -Result “FAIL” -Details $
.Exception.Message
}
#endregion

#region 3. DNS Zones – AD Integrated Check
Write-Log “— Investigating DNS Zones —“

try {
$zones = Get-DnsServerZone | Where-Object { $.IsReverseLookupZone -eq $false -or $.ZoneType -eq ‘Forwarder’ -or $.ZoneName -match ‘in-addr.arpa’ }
$forwardZones = Get-DnsServerZone | Where-Object { $
.IsReverseLookupZone -eq $false -and $.ZoneType -ne ‘Stub’ }
$revZones = Get-DnsServerZone | Where-Object { $
.IsReverseLookupZone -eq $true }

foreach ($zone in $forwardZones) {
    $zoneName = $zone.ZoneName
    $zoneType = $zone.ZoneType
    $isDsIntegrated = $zone.IsDsIntegrated
    $dynamicUpdate = $zone.DynamicUpdate
    $zoneStatus = if ($zone.ZoneType -eq 'Primary' -and $isDsIntegrated) { "PASS" } else { "INFO" }

    Write-Log "Zone: $zoneName | Type: $zoneType | DS-Integrated: $isDsIntegrated | DynamicUpdate: $dynamicUpdate"
    Add-Result -Category "DNS Zones" -Test "Zone: $zoneName" -Result $zoneStatus -Details "Type=$zoneType, DSIntegrated=$isDsIntegrated, DynamicUpdate=$dynamicUpdate"

    # Check scavenging / aging
    try {
        $aging = Get-DnsServerZoneAging -ZoneName $zoneName -ErrorAction Stop
        Write-Log "  -> Aging enabled: $($aging.AgingEnabled), NoRefreshInterval: $($aging.NoRefreshInterval.Hours)h, RefreshInterval: $($aging.RefreshInterval.Hours)h"
        if (-not $aging.AgingEnabled) {
            Add-Result -Category "DNS Zones" -Test "Scavenging on $zoneName" -Result "WARNING" -Details "Aging/Scavenging is NOT enabled. Stale records may accumulate."
        }
    } catch {
        Write-Log "  -> Could not retrieve aging settings for $zoneName" "Warning"
    }
}

if ($revZones.Count -eq 0) {
    Write-Log "No reverse lookup zones found." "Warning"
    Add-Result -Category "DNS Zones" -Test "Reverse Lookup Zones" -Result "WARNING" -Details "No reverse lookup zones detected."
} else {
    foreach ($rz in $revZones) {
        Write-Log "Reverse Zone: $($rz.ZoneName) | Type: $($rz.ZoneType) | DSIntegrated: $($rz.IsDsIntegrated)"
    }
    Add-Result -Category "DNS Zones" -Test "Reverse Lookup Zones" -Result "PASS" -Details "$($revZones.Count) reverse lookup zone(s) present."
}

} catch {
Write-Log “Failed to enumerate DNS zones: $” “Error”
Add-Result -Category “DNS Zones” -Test “Zone Enumeration” -Result “FAIL” -Details $
.Exception.Message
}
#endregion

#region 4. Critical AD DNS Records
Write-Log “— Checking Critical AD DNS Records —“

try {
$domainName = (Get-ADDomain).DNSRoot
$dcName = $env:COMPUTERNAME
$dcIp = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $.IPAddress -notlike ‘127.*’ -and $.IPAddress -notlike ‘169.254.*’ } | Select-Object -First 1).IPAddress

Write-Log "Domain: $domainName"
Write-Log "DC Name: $dcName"
Write-Log "DC IPv4: $dcIp"

# NS records for domain
try {
    $nsRecords = Resolve-DnsName -Name $domainName -Type NS -ErrorAction Stop
    $nsList = ($nsRecords | Where-Object { $_.QueryType -eq 'NS' }).NameHost -join ', '
    Write-Log "NS Records for $domainName : $nsList"
    Add-Result -Category "DNS Records" -Test "NS Records" -Result "PASS" -Details "NS records: $nsList"
} catch {
    Add-Result -Category "DNS Records" -Test "NS Records" -Result "FAIL" -Details "Cannot resolve NS records for $domainName : $_"
}

# LDAP/GC SRV records
$srvTests = @(
    "_ldap._tcp.$domainName",
    "_kerberos._tcp.$domainName",
    "_ldap._tcp.dc._msdcs.$domainName",
    "_ldap._tcp.gc._msdcs.$((Get-ADDomain).Forest)"
)

foreach ($srv in $srvTests) {
    try {
        $srvResult = Resolve-DnsName -Name $srv -Type SRV -ErrorAction Stop
        $targets = ($srvResult | Where-Object { $_.QueryType -eq 'SRV' }).NameTarget -join ', '
        Write-Log "SRV OK: $srv -> $targets" "Success"
        Add-Result -Category "DNS Records" -Test "SRV: $srv" -Result "PASS" -Details "Targets: $targets"
    } catch {
        Write-Log "SRV FAIL: $srv -> $_" "Error"
        Add-Result -Category "DNS Records" -Test "SRV: $srv" -Result "FAIL" -Details $_.Exception.Message
    }
}

# A record for this DC
try {
    $aRec = Resolve-DnsName -Name "$dcName.$domainName" -Type A -ErrorAction Stop
    $resolvedIp = ($aRec | Where-Object { $_.QueryType -eq 'A' }).IPAddress
    Write-Log "A record for $dcName.$domainName resolves to $resolvedIp" "Success"
    Add-Result -Category "DNS Records" -Test "DC A Record" -Result "PASS" -Details "Resolves to: $resolvedIp"
} catch {
    Write-Log "A record for $dcName.$domainName FAILED to resolve." "Error"
    Add-Result -Category "DNS Records" -Test "DC A Record" -Result "FAIL" -Details "Cannot resolve $dcName.$domainName"
}

# Register this DC's records test
try {
    $ipConfig = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "IPEnabled = True"
    foreach ($adapter in $ipConfig) {
        $adapter.SetDNSDomain($domainName) | Out-Null
    }
    # Note: ipconfig /registerdns is non-destructive and re-registers DC DNS records
    Write-Log "Consider running 'ipconfig /registerdns' if SRV/A records are missing." "Warning"
    Add-Result -Category "DNS Records" -Test "Registration Advice" -Result "INFO" -Details "Run 'ipconfig /registerdns' and restart Netlogon if records are missing."
} catch {
    # non-critical
}

} catch {
Write-Log “Error during DNS record checks: $_” “Error”
}
#endregion

#region 5. DNS Client / Adapter Configuration on DC
Write-Log “— Checking DNS Client Settings on DC —“

$adapters = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter “IPEnabled = True”
$loopbackFound = $false
$properDnsConfigured = $false

foreach ($adapter in $adapters) {
$dnsServers = $adapter.DNSServerSearchOrder
$desc = $adapter.Description
Write-Log “Adapter: $desc | DNS Servers: $($dnsServers -join ‘, ‘)”

if ($dnsServers -contains '127.0.0.1') {
    $loopbackFound = $true
}
# Best practice: DC should point to itself (and another DC) for DNS
if ($dnsServers -contains (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.IPAddress -notlike '127.*' -and $_.IPAddress -notlike '169.254.*' } | Select-Object -First 1).IPAddress) {
    $properDnsConfigured = $true
}

}

if ($loopbackFound) {
Add-Result -Category “DNS Client” -Test “Loopback in DNS” -Result “INFO” -Details “127.0.0.1 found in DNS settings. Ensure another DC IP is also configured as secondary.”
} else {
Add-Result -Category “DNS Client” -Test “Loopback in DNS” -Result “WARNING” -Details “127.0.0.1 not found. DCs should typically point to themselves for DNS registration.”
}

Add-Result -Category “DNS Client” -Test “Adapter DNS Config” -Result $(if($properDnsConfigured){“PASS”}else{“WARNING”}) -Details “Review DNS server order on network adapters.”
#endregion

#region 6. DNS Resolution & Forwarder Tests
Write-Log “— Performing External DNS Resolution Tests —“

$testHosts = @(“www.google.com“, “microsoft.com”, “msdcs.$((Get-ADDomain).DNSRoot)”)
foreach ($h in $testHosts) {
try {
$res = Resolve-DnsName -Name $h -Type A -ErrorAction Stop -ErrorVariable err
$ip = ($res | Select-Object -First 1).IPAddress
Write-Log “Resolution OK: $h -> $ip” “Success”
Add-Result -Category “Resolution” -Test “Resolve $h” -Result “PASS” -Details “Resolved to $ip”
} catch {
Write-Log “Resolution FAIL: $h -> $
” “Error”
Add-Result -Category “Resolution” -Test “Resolve $h” -Result “FAIL” -Details $_.Exception.Message
}
}

Test DNS server on port 53

$localIp = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $.IPAddress -notlike ‘127.*’ -and $.IPAddress -notlike ‘169.254.*’ } | Select-Object -First 1).IPAddress
try {
$testDns = Test-NetConnection -ComputerName $localIp -Port 53 -WarningAction SilentlyContinue
if ($testDns.TcpTestSucceeded) {
Write-Log “DNS TCP/53 responding on $localIp” “Success”
Add-Result -Category “Connectivity” -Test “DNS Port 53” -Result “PASS” -Details “TCP port 53 is reachable on $localIp”
} else {
Write-Log “DNS TCP/53 NOT responding on $localIp” “Error”
Add-Result -Category “Connectivity” -Test “DNS Port 53” -Result “FAIL” -Details “TCP port 53 is not responding.”
}
} catch {
Add-Result -Category “Connectivity” -Test “DNS Port 53” -Result “FAIL” -Details $_.Exception.Message
}
#endregion

#region 7. AD Replication & DS-Integrated DNS
Write-Log “— Checking AD Replication (impacts AD-Integrated DNS) —“

try {
Import-Module ActiveDirectory -ErrorAction Stop
$replSummary = Get-ADReplicationPartnerMetadata -Target “$env:COMPUTERNAME” -Partition * -ErrorAction SilentlyContinue
if (-not $replSummary) {
# Single DC environment
Write-Log “No replication partners found. This may be a single-DC environment.” “Warning”
Add-Result -Category “AD Replication” -Test “Replication Partners” -Result “INFO” -Details “No replication partners detected. Single DC or replication health issue.”
} else {
foreach ($partner in $replSummary) {
$lastRep = $partner.LastReplicationSuccess
$partnerServer = $partner.Partner
$partition = $partner.Partition
$hoursAgo = (Get-Date) – $lastRep
Write-Log “Replication: $partition with $partnerServer | Last Success: $lastRep ($([math]::Round($hoursAgo.TotalHours,1)) hours ago)”
if ($hoursAgo.TotalHours -gt 24) {
Add-Result -Category “AD Replication” -Test “Repl: $partition” -Result “FAIL” -Details “Last success was $([math]::Round($hoursAgo.TotalHours,1)) hours ago (>24h).”
} else {
Add-Result -Category “AD Replication” -Test “Repl: $partition” -Result “PASS” -Details “Last success $([math]::Round($hoursAgo.TotalHours,1)) hours ago.”
}
}
}

# Check for replication errors via repadmin (if available)
if (Get-Command repadmin.exe -ErrorAction SilentlyContinue) {
    $repadminOut = & repadmin.exe /showrepl /csv 2>$null
    if ($repadminOut) {
        Write-Log "Repadmin /showrepl data collected (review manually if needed)." "Info"
        Add-Result -Category "AD Replication" -Test "Repadmin" -Result "INFO" -Details "repadmin /showrepl executed. Check CSV output manually."
    }
}

} catch {
Write-Log “Could not evaluate AD replication: $” “Warning”
Add-Result -Category “AD Replication” -Test “Replication Check” -Result “WARNING” -Details $
.Exception.Message
}
#endregion

#region 8. DCDiag DNS Tests
if ($IncludeDCDiag) {
Write-Log “— Running DCDiag (DNS-focused) —“
if (Get-Command dcdiag.exe -ErrorAction SilentlyContinue) {
$dcdiagTests = @(“DNS”, “DnsReg”, “DsGetDc”, “Advertising”, “FsmoCheck”)
foreach ($t in $dcdiagTests) {
Write-Log “Running dcdiag /test:$t …”
$output = & dcdiag.exe /test:$t /q 2>&1
$outputStr = $output | Out-String
if ($outputStr -match “failed|error|fail” -or $LASTEXITCODE -ne 0) {
Write-Log “DCDiag /test:$t detected issues.” “Error”
Add-Result -Category “DCDiag” -Test “dcdiag /test:$t” -Result “FAIL” -Details ($outputStr.Substring(0,[Math]::Min(500,$outputStr.Length)))
} else {
Write-Log “DCDiag /test:$t passed.” “Success”
Add-Result -Category “DCDiag” -Test “dcdiag /test:$t” -Result “PASS” -Details “No errors reported.”
}
}
} else {
Write-Log “dcdiag.exe not found. Skipping DCDiag tests.” “Warning”
Add-Result -Category “DCDiag” -Test “DCDiag Availability” -Result “WARNING” -Details “dcdiag.exe not available.”
}
} else {
Write-Log “Skipping DCDiag tests (use -IncludeDCDiag to enable).” “Info”
}
#endregion

#region 9. Event Logs
if ($IncludeEventLogs) {
Write-Log “— Collecting DNS and Directory Service Event Log Errors (last $EventLogDays day(s)) —“
$startTime = (Get-Date).AddDays(-$EventLogDays)

$dnsEvents = Get-WinEvent -FilterHashtable @{LogName='DNS Server'; Level=1,2; StartTime=$startTime} -ErrorAction SilentlyContinue
$dsEvents  = Get-WinEvent -FilterHashtable @{LogName='Directory Service'; Level=1,2; StartTime=$startTime} -ErrorAction SilentlyContinue

if ($dnsEvents) {
    Write-Log "Found $($dnsEvents.Count) DNS Server error/critical event(s)." "Error"
    $dnsEvents | Select-Object -First 5 | ForEach-Object {
        Write-Log "  DNS Event ID $($_.Id) at $($_.TimeCreated): $($_.Message.Substring(0,[Math]::Min(200,$_.Message.Length)))..." "Error"
    }
    Add-Result -Category "Event Logs" -Test "DNS Server Errors" -Result "FAIL" -Details "$($dnsEvents.Count) error/critical events in last $EventLogDays day(s)."
} else {
    Write-Log "No DNS Server error/critical events in last $EventLogDays day(s)." "Success"
    Add-Result -Category "Event Logs" -Test "DNS Server Errors" -Result "PASS" -Details "No error/critical events found."
}

if ($dsEvents) {
    Write-Log "Found $($dsEvents.Count) Directory Service error/critical event(s)." "Error"
    Add-Result -Category "Event Logs" -Test "Directory Service Errors" -Result "FAIL" -Details "$($dsEvents.Count) error/critical events in last $EventLogDays day(s)."
} else {
    Write-Log "No Directory Service error/critical events in last $EventLogDays day(s)." "Success"
    Add-Result -Category "Event Logs" -Test "Directory Service Errors" -Result "PASS" -Details "No error/critical events found."
}

} else {
Write-Log “Skipping Event Log analysis (use -IncludeEventLogs to enable).” “Info”
}
#endregion

#region 10. Scavenging & Stale Records Summary
Write-Log “— Checking Server-Level Scavenging —“
try {
$scavenging = Get-DnsServerScavenging
Write-Log “Scavenging Enabled: $($scavenging.ScavengingEnabled), Scavenging Interval: $($scavenging.ScavengingInterval)”
if (-not $scavenging.ScavengingEnabled) {
Add-Result -Category “DNS Maintenance” -Test “Server Scavenging” -Result “WARNING” -Details “Automatic scavenging is disabled at server level.”
} else {
Add-Result -Category “DNS Maintenance” -Test “Server Scavenging” -Result “PASS” -Details “Scavenging enabled. Interval: $($scavenging.ScavengingInterval)”
}
} catch {
Write-Log “Could not retrieve scavenging settings: $_” “Warning”
}
#endregion

#region 11. Common Remediation Advice Summary
Write-Log “— Generating Remediation Advice —“

$remediation = @()
$failures = $script:Results | Where-Object { $.Result -eq ‘FAIL’ }
$warnings = $script:Results | Where-Object { $
.Result -eq ‘WARNING’ }

if ($failures | Where-Object { $.Test -eq ‘DNS Service’ }) {
$remediation += “DNS Service is not running. Run: Start-Service DNS; Set-Service DNS -StartupType Automatic”
}
if ($warnings | Where-Object { $
.Test -like ‘Scavenging‘ }) {
$remediation += “Enable scavenging: Set-DnsServerScavenging -ScavengingEnabled `$true -ScavengingInterval 7.00:00:00”
}
if ($failures | Where-Object { $.Category -eq ‘DNS Records’ -and $.Test -like ‘SRV:*’ }) {
$remediation += “Missing SRV records. Run: ipconfig /registerdns ; then restart-service Netlogon”
}
if ($failures | Where-Object { $.Category -eq ‘AD Replication’ }) {
$remediation += “Replication issues detected. Investigate with: repadmin /replsummary and repadmin /showreps”
}
if ($warnings | Where-Object { $
.Test -eq ‘Forwarders Configured’ }) {
$remediation += “No forwarders configured. If external resolution is needed, add via DNS console or Set-DnsServerForwarder.”
}

if ($remediation.Count -gt 0) {
Write-Log “n========== REMEDIATION SUGGESTIONS ==========" "Warning" $remediation | ForEach-Object { Write-Log $_ "Warning" } } else { Write-Log "nNo critical remediation suggestions generated. Review INFO/WARNING items above.” “Success”
}
#endregion

#region Export & Finalize
$script:Results | Export-Csv -Path $ReportPath -NoTypeInformation -Encoding UTF8 -Force
Write-Log “`n========== Investigation Complete ==========”
Write-Log “CSV Report: $ReportPath”
Write-Log “Log File: $LogPath”
Write-Log “Total Checks: $($script:Results.Count)”
Write-Log “Failures: $($failures.Count) | Warnings: $($warnings.Count) | Pass/Info: $(($script:Results | Where-Object {$_.Result -in ‘PASS’,’INFO’}).Count)”

Also output summary to console as a table

$script:Results | Format-Table -AutoSize | Out-String | Write-Host
#endregion

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top