The Domain Controller Detective: A PowerShell Script That Actually Tells You What You Need to Know

I’ve been managing domain controllers for longer than I care to admit, and one thing never changes: when something goes sideways, you need information fast. Not the sanitized dashboard view that tells you everything’s “healthy” while users can’t log in. Real information about what’s actually running, where the bottlenecks are, and whether your hardware is about to give up the ghost.

The script I’m sharing today solves a problem every Windows admin faces. Instead of clicking through Server Manager, DNS Manager, Active Directory Users and Computers, and half a dozen other consoles just to get a basic health check, this PowerShell script pulls everything that matters into one comprehensive report.

Why This Actually Matters

Domain controllers are the backbone of your Windows infrastructure. When they’re happy, nobody thinks about them. When they’re not, everyone knows about it immediately. But here’s the thing: most monitoring tools either give you too little information or bury the useful stuff under layers of enterprise complexity.

This script takes a different approach. It assumes you’re smart enough to interpret the data yourself and just need it organized properly. No traffic light dashboards, no “health scores” that don’t mean anything. Just the facts.

What It Actually Does

The script breaks down domain controller information into logical sections that mirror how you actually troubleshoot problems:

Hardware baseline comes first because if your CPU is pegged or you’re out of memory, nothing else matters. The processor and memory functions give you real numbers, not percentages that require mental math.

Storage details follow because domain controllers are surprisingly disk-intensive. SYSVOL replication, log files, and database operations can hammer your drives. The disk function shows not just free space, but percentages so you can quickly spot problems.

Network configuration gets its own section because DNS issues kill more domains than hardware failures. If your network settings are wrong, everything downstream breaks in mysterious ways.

The Active Directory specifics pull forest and domain functional levels, which matter more than most admins realize. Mixed functional levels cause weird replication issues that can take days to track down.

DNS server details include forwarders and zone information. I’ve seen too many outages caused by DNS forwarders pointing to dead servers or zones that should be AD-integrated but aren’t.

DFS information rounds out the file services picture. If you’re using DFS (and you should be), this tells you whether replication groups are healthy without diving into the management console.

Finally, critical services status gives you a quick sanity check. Services like Netlogon and DNS should always be running on a domain controller, but Windows has a habit of stopping things without telling you.

The Real-World Gotchas

I’ve learned a few things running this script across different environments. First, it assumes you have the appropriate management tools installed. On Server Core installations, some functions will gracefully fail with yellow warnings instead of crashing the whole script. That’s intentional.

Second, the error handling around DNS and DFS functions exists because not every domain controller runs every role. Your read-only domain controllers probably aren’t running DFS, and that’s fine.

The memory calculation converts bytes to gigabytes because nobody thinks in bytes anymore. Same with the disk space percentages; when you’re troubleshooting at 2 AM, you don’t want to do math to figure out if that 847GB free space on a 2TB drive is actually a problem.

When This Saves Your Day

This script shines during those “everything’s broken” moments when you need to quickly assess multiple domain controllers. Run it on each DC, compare the outputs, and patterns emerge quickly.

I’ve used variations of this script to catch hardware failures before they became outages, identify misconfigured DNS settings that were causing authentication delays, and spot DFS replication problems that were making file shares unreliable.

The section headers make it easy to skip to what you care about. If users are complaining about slow logons, jump straight to the network and DNS sections. If performance is generally sluggish, start with hardware details.

Making It Your Own

The beauty of PowerShell is how easily you can modify this script. Add sections for specific roles your domain controllers handle, or remove sections that don’t apply to your environment. The modular function approach makes changes straightforward.

You might want to export results to a file for documentation, add timestamp headers for regular health checks, or integrate the output with your monitoring system. The foundation is solid; build whatever makes sense for your situation.

The script assumes you’re running it locally on the domain controller, but you could easily adapt it for remote execution if your security policies allow it.

Domain controllers don’t have to be mysterious black boxes. With the right information presented clearly, managing them becomes much more predictable. This script gives you that information without the usual enterprise software overhead or the tedium of clicking through multiple management consoles.

Save yourself some time and frustration. Your future self will thank you when the inevitable 2 AM phone call comes in.

<#
.SYNOPSIS
Comprehensive Windows Domain Controller Information Gathering Script

.DESCRIPTION
Collects detailed system information for Windows Domain Controllers
Gathers hardware, network, Active Directory, and service details
#>

# Function to create section headers
function Write-SectionHeader {
    param([string]$Title)
    Write-Host "`n==================== $Title ====================" -ForegroundColor Cyan
}

# Processor Information
function Get-ProcessorInfo {
    Write-SectionHeader "Processor Details"
    Get-WmiObject Win32_Processor | Format-List Name, 
        @{Name='Clock Speed (GHz)'; Expression={$_.MaxClockSpeed / 1000}}, 
        NumberOfCores, 
        NumberOfLogicalProcessors, 
        Manufacturer
}

# Memory Information
function Get-MemoryDetails {
    Write-SectionHeader "Memory (RAM) Information"
    $memoryModules = Get-WmiObject Win32_PhysicalMemory
    $totalMemory = ($memoryModules | Measure-Object -Property Capacity -Sum).Sum / 1GB

    Write-Host "Total Physical Memory: $("{0:N2}" -f $totalMemory) GB"
    $memoryModules | Format-Table Manufacturer, PartNumber, Capacity, Speed
}

# Disk Information
function Get-DiskInfo {
    Write-SectionHeader "Disk Information"
    Get-WmiObject Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Format-Table `
        DeviceID, 
        @{Name='Size (GB)'; Expression={[math]::Round($_.Size/1GB, 2)}}, 
        @{Name='Free Space (GB)'; Expression={[math]::Round($_.FreeSpace/1GB, 2)}}, 
        @{Name='Free Space (%)'; Expression={[math]::Round(($_.FreeSpace/$_.Size)*100, 2)}}
}

# Domain Controller Specific Information
function Get-DomainControllerInfo {
    Write-SectionHeader "Domain Controller Details"
    # Check if AD module is available
    if (Get-Module -ListAvailable ActiveDirectory) {
        Import-Module ActiveDirectory
        
        # Forest and Domain Information
        $forest = Get-ADForest
        $domain = Get-ADDomain

        Write-Host "Forest Name: $($forest.Name)"
        Write-Host "Domain Name: $($domain.DNSRoot)"
        Write-Host "Domain Functional Level: $($domain.DomainMode)"
        Write-Host "Forest Functional Level: $($forest.ForestMode)"

        # Domain Controllers in the forest
        Write-Host "`nDomain Controllers:"
        $forest.GlobalCatalogs
    }
    else {
        Write-Host "Active Directory PowerShell module not available." -ForegroundColor Yellow
    }
}

# DNS Server Information
function Get-DNSServerInfo {
    Write-SectionHeader "DNS Server Details"
    try {
        $dnsSettings = Get-DnsServerSetting -All -ErrorAction Stop
        $forwarders = Get-DnsServerForwarder

        Write-Host "DNS Server Name: $env:COMPUTERNAME"
        Write-Host "DNS Forwarders:"
        $forwarders.IPAddress | ForEach-Object { Write-Host $_ }

        Write-Host "`nDNS Zones:"
        Get-DnsServerZone | Format-Table ZoneName, ZoneType, IsDsIntegrated
    }
    catch {
        Write-Host "Unable to retrieve DNS information. Ensure DNS management tools are installed." -ForegroundColor Yellow
    }
}

# Distributed File System (DFS) Information
function Get-DFSInfo {
    Write-SectionHeader "Distributed File System (DFS) Details"
    try {
        $dfsNamespaces = Get-DfsnRoot -ErrorAction Stop
        
        Write-Host "DFS Namespaces:"
        $dfsNamespaces | Format-Table Path, State, Type

        Write-Host "`nDFS Replication Groups:"
        Get-DfsReplicationGroup | Format-Table GroupName, Description
    }
    catch {
        Write-Host "Unable to retrieve DFS information. Ensure DFS management tools are installed." -ForegroundColor Yellow
    }
}

# Important Windows Services
function Get-CriticalServices {
    Write-SectionHeader "Critical Windows Services"
    $criticalServices = @(
        "Active Directory Domain Services",
        "DNS",
        "Netlogon",
        "DFS",
        "DHCP Server",
        "Windows Time"
    )

    $criticalServices | ForEach-Object {
        $service = Get-Service $_ -ErrorAction SilentlyContinue
        if ($service) {
            Write-Host "$($service.Name): $($service.Status)"
        }
    }
}

# Network Information
function Get-NetworkDetails {
    Write-SectionHeader "Network Configuration"
    Get-NetIPConfiguration | Format-List InterfaceAlias, IPv4Address, DNSServer
}

# Main Execution
function Invoke-ServerInfoGathering {
    Get-ProcessorInfo
    Get-MemoryDetails
    Get-DiskInfo
    Get-NetworkDetails
    Get-DomainControllerInfo
    Get-DNSServerInfo
    Get-DFSInfo
    Get-CriticalServices

    Write-Host "`n==================== Script Complete ====================" -ForegroundColor Green
}

# Run the main function
Invoke-ServerInfoGathering
Code language: PowerShell (powershell)

Leave a Reply