Comprehensive diagnostic script to check Active Directory domain controller health, replication status, and identify common issues.

Overview

This script performs a complete health assessment of your Active Directory environment including domain controller diagnostics, replication status, FSMO role verification, DNS health, and service status checks.

Use Case: Routine health checks, troubleshooting replication issues, validating DC configuration, or diagnosing authentication problems.

Platform: Windows Server 2012 R2+ Requirements: Domain Administrator privileges, Active Directory module Execution Time: 3-5 minutes depending on domain size

The Script

Lang: powershell
  1<#
  2.SYNOPSIS
  3    Active Directory health check script
  4
  5.DESCRIPTION
  6    Performs comprehensive health checks on Active Directory including:
  7    - DCDiag tests (connectivity, replication, DNS, services)
  8    - Replication status with repadmin
  9    - FSMO role holder verification
 10    - Domain controller service status
 11    - DNS SRV record validation
 12    - Time synchronization check
 13    - Event log analysis for critical AD errors
 14
 15.PARAMETER ExportPath
 16    Path to export HTML report. If not specified, results display in console only.
 17
 18.PARAMETER SkipDNSTests
 19    Skip DNS SRV record validation tests
 20
 21.PARAMETER QuickCheck
 22    Perform quick health check (skips detailed event log analysis)
 23
 24.EXAMPLE
 25    .\Test-ADHealth.ps1
 26    Runs full health check with console output
 27
 28.EXAMPLE
 29    .\Test-ADHealth.ps1 -ExportPath "C:\Reports\ADHealth.html"
 30    Runs health check and exports HTML report
 31
 32.EXAMPLE
 33    .\Test-ADHealth.ps1 -QuickCheck
 34    Runs quick health check without detailed event log analysis
 35
 36.NOTES
 37    Author: glyph.sh
 38    Requires: Domain Administrator privileges, AD PowerShell module
 39    Reference: https://glyph.sh/kb/active-directory-troubleshooting/
 40#>
 41
 42[CmdletBinding()]
 43param(
 44    [string]$ExportPath,
 45    [switch]$SkipDNSTests,
 46    [switch]$QuickCheck
 47)
 48
 49#Requires -RunAsAdministrator
 50#Requires -Modules ActiveDirectory
 51
 52# Initialize results collection
 53$script:HealthResults = @{
 54    Timestamp = Get-Date
 55    OverallStatus = "Healthy"
 56    Issues = @()
 57    Warnings = @()
 58}
 59
 60function Write-HealthStatus {
 61    param(
 62        [string]$Message,
 63        [ValidateSet('Info', 'Success', 'Warning', 'Error')]
 64        [string]$Level = 'Info'
 65    )
 66
 67    $color = switch ($Level) {
 68        'Success' { 'Green' }
 69        'Warning' { 'Yellow' }
 70        'Error' { 'Red' }
 71        default { 'White' }
 72    }
 73
 74    $prefix = switch ($Level) {
 75        'Success' { '[OK]' }
 76        'Warning' { '[WARN]' }
 77        'Error' { '[ERROR]' }
 78        default { '[INFO]' }
 79    }
 80
 81    Write-Host "$prefix $Message" -ForegroundColor $color
 82
 83    if ($Level -eq 'Error') {
 84        $script:HealthResults.Issues += $Message
 85        $script:HealthResults.OverallStatus = "Critical"
 86    }
 87    elseif ($Level -eq 'Warning' -and $script:HealthResults.OverallStatus -eq "Healthy") {
 88        $script:HealthResults.Warnings += $Message
 89        $script:HealthResults.OverallStatus = "Warning"
 90    }
 91}
 92
 93Write-Host "========================================" -ForegroundColor Cyan
 94Write-Host " Active Directory Health Check" -ForegroundColor Cyan
 95Write-Host "========================================" -ForegroundColor Cyan
 96Write-Host ""
 97
 98# Get domain information
 99try {
100    $domain = Get-ADDomain -ErrorAction Stop
101    $forest = Get-ADForest -ErrorAction Stop
102    Write-HealthStatus "Domain: $($domain.DNSRoot)" -Level Info
103    Write-HealthStatus "Forest: $($forest.Name)" -Level Info
104    Write-Host ""
105}
106catch {
107    Write-HealthStatus "Failed to retrieve domain information: $($_.Exception.Message)" -Level Error
108    exit 1
109}
110
111# Get all domain controllers
112try {
113    $domainControllers = Get-ADDomainController -Filter * | Sort-Object Name
114    Write-HealthStatus "Found $($domainControllers.Count) domain controller(s)" -Level Success
115    Write-Host ""
116}
117catch {
118    Write-HealthStatus "Failed to retrieve domain controllers: $($_.Exception.Message)" -Level Error
119    exit 1
120}
121
122# Check 1: Domain Controller Services
123Write-Host "[1/7] Checking Domain Controller Services..." -ForegroundColor Yellow
124Write-Host ""
125
126$criticalServices = @('ADWS', 'KDC', 'NTDS', 'DNS', 'Netlogon', 'W32Time')
127
128foreach ($dc in $domainControllers) {
129    Write-Host "  Checking $($dc.Name)..." -ForegroundColor Cyan
130
131    foreach ($serviceName in $criticalServices) {
132        try {
133            $service = Get-Service -Name $serviceName -ComputerName $dc.HostName -ErrorAction Stop
134
135            if ($service.Status -eq 'Running') {
136                Write-HealthStatus "    $serviceName is running" -Level Success
137            }
138            else {
139                Write-HealthStatus "    $serviceName is $($service.Status) on $($dc.Name)" -Level Error
140            }
141        }
142        catch {
143            Write-HealthStatus "    Cannot check $serviceName on $($dc.Name): $($_.Exception.Message)" -Level Warning
144        }
145    }
146    Write-Host ""
147}
148
149# Check 2: FSMO Roles
150Write-Host "[2/7] Verifying FSMO Role Holders..." -ForegroundColor Yellow
151Write-Host ""
152
153try {
154    $pdcEmulator = $domain.PDCEmulator
155    $ridMaster = $domain.RIDMaster
156    $infraMaster = $domain.InfrastructureMaster
157    $schemaMaster = $forest.SchemaMaster
158    $domainNamingMaster = $forest.DomainNamingMaster
159
160    Write-HealthStatus "  PDC Emulator: $pdcEmulator" -Level Info
161    Write-HealthStatus "  RID Master: $ridMaster" -Level Info
162    Write-HealthStatus "  Infrastructure Master: $infraMaster" -Level Info
163    Write-HealthStatus "  Schema Master: $schemaMaster" -Level Info
164    Write-HealthStatus "  Domain Naming Master: $domainNamingMaster" -Level Info
165
166    # Verify FSMO role holders are online
167    $fsmoHolders = @($pdcEmulator, $ridMaster, $infraMaster, $schemaMaster, $domainNamingMaster) | Select-Object -Unique
168
169    foreach ($fsmo in $fsmoHolders) {
170        $dcName = $fsmo.Split('.')[0]
171        $dcOnline = $domainControllers | Where-Object { $_.Name -eq $dcName }
172
173        if (-not $dcOnline) {
174            Write-HealthStatus "  FSMO role holder $fsmo is not responding" -Level Error
175        }
176    }
177}
178catch {
179    Write-HealthStatus "  Failed to retrieve FSMO roles: $($_.Exception.Message)" -Level Error
180}
181
182Write-Host ""
183
184# Check 3: Replication Status
185Write-Host "[3/7] Checking Replication Status..." -ForegroundColor Yellow
186Write-Host ""
187
188foreach ($dc in $domainControllers) {
189    Write-Host "  Checking replication on $($dc.Name)..." -ForegroundColor Cyan
190
191    try {
192        $replStatus = repadmin /showrepl $dc.HostName 2>&1
193
194        if ($LASTEXITCODE -eq 0) {
195            # Check for replication errors
196            $errors = $replStatus | Select-String -Pattern "last (error|failure)"
197
198            if ($errors) {
199                Write-HealthStatus "    Replication errors detected on $($dc.Name)" -Level Error
200                $errors | ForEach-Object { Write-Host "      $_" -ForegroundColor Red }
201            }
202            else {
203                Write-HealthStatus "    Replication is healthy" -Level Success
204            }
205        }
206        else {
207            Write-HealthStatus "    Failed to check replication on $($dc.Name)" -Level Warning
208        }
209    }
210    catch {
211        Write-HealthStatus "    Error checking replication: $($_.Exception.Message)" -Level Warning
212    }
213}
214
215Write-Host ""
216
217# Check replication summary
218Write-Host "  Replication Summary:" -ForegroundColor Cyan
219try {
220    $replSummary = repadmin /replsummary 2>&1
221
222    if ($LASTEXITCODE -eq 0) {
223        $replSummary | Select-String -Pattern "errors|failures" | ForEach-Object {
224            if ($_ -match "0 (/|errors|failures)") {
225                Write-HealthStatus "    $_" -Level Success
226            }
227            else {
228                Write-HealthStatus "    $_" -Level Warning
229            }
230        }
231    }
232}
233catch {
234    Write-HealthStatus "  Could not retrieve replication summary" -Level Warning
235}
236
237Write-Host ""
238
239# Check 4: DCDiag Tests
240Write-Host "[4/7] Running DCDiag Tests..." -ForegroundColor Yellow
241Write-Host ""
242
243foreach ($dc in $domainControllers) {
244    Write-Host "  Running diagnostics on $($dc.Name)..." -ForegroundColor Cyan
245
246    # Run core DCDiag tests
247    $tests = @('Connectivity', 'Replications', 'Services', 'Advertising', 'FsmoCheck')
248
249    foreach ($test in $tests) {
250        try {
251            $result = dcdiag /s:$($dc.HostName) /test:$test 2>&1
252
253            if ($result -match "passed test $test") {
254                Write-HealthStatus "    $test test passed" -Level Success
255            }
256            elseif ($result -match "failed test $test") {
257                Write-HealthStatus "    $test test failed on $($dc.Name)" -Level Error
258            }
259            else {
260                Write-HealthStatus "    $test test inconclusive on $($dc.Name)" -Level Warning
261            }
262        }
263        catch {
264            Write-HealthStatus "    Error running $test test: $($_.Exception.Message)" -Level Warning
265        }
266    }
267    Write-Host ""
268}
269
270# Check 5: DNS Health
271if (-not $SkipDNSTests) {
272    Write-Host "[5/7] Checking DNS Configuration..." -ForegroundColor Yellow
273    Write-Host ""
274
275    # Test critical SRV records
276    $srvRecords = @(
277        "_ldap._tcp.dc._msdcs.$($domain.DNSRoot)",
278        "_kerberos._tcp.dc._msdcs.$($domain.DNSRoot)",
279        "_ldap._tcp.$($domain.DNSRoot)",
280        "_kerberos._tcp.$($domain.DNSRoot)"
281    )
282
283    foreach ($record in $srvRecords) {
284        try {
285            $result = Resolve-DnsName -Name $record -Type SRV -ErrorAction Stop
286
287            if ($result) {
288                Write-HealthStatus "  SRV record $record resolved successfully" -Level Success
289            }
290        }
291        catch {
292            Write-HealthStatus "  Failed to resolve SRV record $record" -Level Error
293        }
294    }
295
296    Write-Host ""
297
298    # Run DCDiag DNS test
299    Write-Host "  Running comprehensive DNS tests..." -ForegroundColor Cyan
300    try {
301        $dnsTest = dcdiag /test:DNS /v 2>&1
302
303        if ($dnsTest -match "failed") {
304            Write-HealthStatus "  DNS test detected issues" -Level Warning
305            $dnsTest | Select-String -Pattern "failed|error" | ForEach-Object {
306                Write-Host "    $_" -ForegroundColor Yellow
307            }
308        }
309        else {
310            Write-HealthStatus "  DNS tests passed" -Level Success
311        }
312    }
313    catch {
314        Write-HealthStatus "  Could not complete DNS tests" -Level Warning
315    }
316
317    Write-Host ""
318}
319else {
320    Write-Host "[5/7] Skipping DNS tests (SkipDNSTests parameter used)" -ForegroundColor Gray
321    Write-Host ""
322}
323
324# Check 6: Time Synchronization
325Write-Host "[6/7] Checking Time Synchronization..." -ForegroundColor Yellow
326Write-Host ""
327
328foreach ($dc in $domainControllers) {
329    try {
330        $timeConfig = w32tm /query /computer:$($dc.HostName) /configuration 2>&1
331        $timeStatus = w32tm /query /computer:$($dc.HostName) /status 2>&1
332
333        if ($dc.OperationMasterRoles -contains 'PDCEmulator') {
334            Write-HealthStatus "  $($dc.Name) is PDC Emulator (time source for domain)" -Level Info
335
336            if ($timeStatus -match "Source:.*Local CMOS") {
337                Write-HealthStatus "    WARNING: PDC using local CMOS, should sync to external source" -Level Warning
338            }
339        }
340        else {
341            if ($timeStatus -match "Source:.*$pdcEmulator") {
342                Write-HealthStatus "  $($dc.Name) is syncing with PDC Emulator" -Level Success
343            }
344            else {
345                Write-HealthStatus "  $($dc.Name) may not be syncing with PDC Emulator" -Level Warning
346            }
347        }
348    }
349    catch {
350        Write-HealthStatus "  Could not check time sync on $($dc.Name)" -Level Warning
351    }
352}
353
354Write-Host ""
355
356# Check 7: Event Log Analysis
357if (-not $QuickCheck) {
358    Write-Host "[7/7] Analyzing Event Logs for Critical AD Errors..." -ForegroundColor Yellow
359    Write-Host ""
360
361    $criticalEventIDs = @{
362        2042 = "It has been too long since this machine last replicated"
363        1311 = "The KDC cannot find a suitable certificate to use for smart card logon"
364        1645 = "Active Directory Domain Services did not find any writable domain controllers"
365        2087 = "DNS lookup failure caused replication to fail"
366        2088 = "Replication access was denied"
367    }
368
369    foreach ($dc in $domainControllers) {
370        Write-Host "  Checking $($dc.Name) event logs..." -ForegroundColor Cyan
371
372        foreach ($eventID in $criticalEventIDs.Keys) {
373            try {
374                $events = Get-WinEvent -ComputerName $dc.HostName -FilterHashtable @{
375                    LogName = 'Directory Service', 'System'
376                    ID = $eventID
377                    StartTime = (Get-Date).AddDays(-7)
378                } -MaxEvents 5 -ErrorAction SilentlyContinue
379
380                if ($events) {
381                    Write-HealthStatus "    Event ID $eventID found: $($criticalEventIDs[$eventID])" -Level Warning
382                    Write-Host "      Count in last 7 days: $($events.Count)" -ForegroundColor Yellow
383                }
384            }
385            catch {
386                # Silently continue if event not found or access denied
387            }
388        }
389    }
390
391    Write-Host ""
392}
393else {
394    Write-Host "[7/7] Skipping event log analysis (QuickCheck parameter used)" -ForegroundColor Gray
395    Write-Host ""
396}
397
398# Summary
399Write-Host "========================================" -ForegroundColor Cyan
400Write-Host " Health Check Summary" -ForegroundColor Cyan
401Write-Host "========================================" -ForegroundColor Cyan
402Write-Host ""
403
404$statusColor = switch ($script:HealthResults.OverallStatus) {
405    'Healthy' { 'Green' }
406    'Warning' { 'Yellow' }
407    'Critical' { 'Red' }
408}
409
410Write-Host "Overall Status: $($script:HealthResults.OverallStatus)" -ForegroundColor $statusColor
411Write-Host "Scan Time: $($script:HealthResults.Timestamp)" -ForegroundColor White
412Write-Host ""
413
414if ($script:HealthResults.Issues.Count -gt 0) {
415    Write-Host "Critical Issues Found: $($script:HealthResults.Issues.Count)" -ForegroundColor Red
416    $script:HealthResults.Issues | ForEach-Object {
417        Write-Host "  - $_" -ForegroundColor Red
418    }
419    Write-Host ""
420}
421
422if ($script:HealthResults.Warnings.Count -gt 0) {
423    Write-Host "Warnings: $($script:HealthResults.Warnings.Count)" -ForegroundColor Yellow
424    $script:HealthResults.Warnings | ForEach-Object {
425        Write-Host "  - $_" -ForegroundColor Yellow
426    }
427    Write-Host ""
428}
429
430if ($script:HealthResults.OverallStatus -eq "Healthy") {
431    Write-Host "No critical issues detected!" -ForegroundColor Green
432    Write-Host ""
433}
434
435# Export HTML report if requested
436if ($ExportPath) {
437    Write-Host "Exporting report to $ExportPath..." -ForegroundColor Cyan
438
439    $html = @"
440<!DOCTYPE html>
441<html>
442<head>
443    <title>Active Directory Health Check Report</title>
444    <style>
445        body { font-family: Arial, sans-serif; margin: 20px; }
446        h1 { color: #0066cc; }
447        h2 { color: #333; border-bottom: 2px solid #0066cc; padding-bottom: 5px; }
448        .healthy { color: green; font-weight: bold; }
449        .warning { color: orange; font-weight: bold; }
450        .critical { color: red; font-weight: bold; }
451        .info { color: #333; }
452        ul { margin: 10px 0; }
453        li { margin: 5px 0; }
454        .timestamp { color: #666; font-size: 0.9em; }
455    </style>
456</head>
457<body>
458    <h1>Active Directory Health Check Report</h1>
459    <p class="timestamp">Generated: $($script:HealthResults.Timestamp)</p>
460    <p>Domain: $($domain.DNSRoot)</p>
461    <p>Forest: $($forest.Name)</p>
462
463    <h2>Overall Status: <span class="$($script:HealthResults.OverallStatus.ToLower())">$($script:HealthResults.OverallStatus)</span></h2>
464
465    <h2>Domain Controllers</h2>
466    <ul>
467$(foreach ($dc in $domainControllers) { "        <li>$($dc.Name) - $($dc.Site)</li>`n" })
468    </ul>
469
470    <h2>FSMO Role Holders</h2>
471    <ul>
472        <li>PDC Emulator: $pdcEmulator</li>
473        <li>RID Master: $ridMaster</li>
474        <li>Infrastructure Master: $infraMaster</li>
475        <li>Schema Master: $schemaMaster</li>
476        <li>Domain Naming Master: $domainNamingMaster</li>
477    </ul>
478
479    $(if ($script:HealthResults.Issues.Count -gt 0) {
480        "<h2>Critical Issues</h2><ul>" +
481        ($script:HealthResults.Issues | ForEach-Object { "<li class='critical'>$_</li>" }) -join "`n" +
482        "</ul>"
483    })
484
485    $(if ($script:HealthResults.Warnings.Count -gt 0) {
486        "<h2>Warnings</h2><ul>" +
487        ($script:HealthResults.Warnings | ForEach-Object { "<li class='warning'>$_</li>" }) -join "`n" +
488        "</ul>"
489    })
490
491    <h2>Recommendations</h2>
492    <ul>
493        <li>Review and resolve any critical issues immediately</li>
494        <li>Schedule regular health checks (weekly recommended)</li>
495        <li>Monitor replication status continuously</li>
496        <li>Ensure proper backup procedures are in place</li>
497        <li>Keep domain controllers patched and up to date</li>
498    </ul>
499</body>
500</html>
501"@
502
503    try {
504        $html | Out-File -FilePath $ExportPath -Encoding UTF8
505        Write-HealthStatus "Report exported successfully" -Level Success
506    }
507    catch {
508        Write-HealthStatus "Failed to export report: $($_.Exception.Message)" -Level Error
509    }
510}
511
512Write-Host ""
513Write-Host "Health check complete!" -ForegroundColor Cyan
514Write-Host ""
515
516# Return results object for further processing
517return $script:HealthResults

Usage

Basic Health Check

Run a complete health check with console output:

Lang: powershell
1.\Test-ADHealth.ps1

Export HTML Report

Generate an HTML report for documentation:

Lang: powershell
1.\Test-ADHealth.ps1 -ExportPath "C:\Reports\ADHealth_$(Get-Date -Format 'yyyyMMdd').html"

Quick Check

Perform a quick health check without event log analysis:

Lang: powershell
1.\Test-ADHealth.ps1 -QuickCheck

Skip DNS Tests

Run health check without DNS validation (useful in split-DNS environments):

Lang: powershell
1.\Test-ADHealth.ps1 -SkipDNSTests

What It Does

1. Domain Controller Services

Verifies that critical AD services are running on all DCs:

  • ADWS (Active Directory Web Services)
  • KDC (Kerberos Key Distribution Center)
  • NTDS (Active Directory Domain Services)
  • DNS (Domain Name System)
  • Netlogon (Net Logon Service)
  • W32Time (Windows Time Service)

2. FSMO Role Verification

Checks and displays all five FSMO role holders:

  • PDC Emulator
  • RID Master
  • Infrastructure Master
  • Schema Master
  • Domain Naming Master

Validates that FSMO role holders are online and responding.

3. Replication Status

Uses repadmin to check:

  • Replication partners for each DC
  • Last replication success/failure
  • Replication errors and warnings
  • Overall replication summary

4. DCDiag Tests

Runs comprehensive diagnostic tests:

  • Connectivity: Network connectivity between DCs
  • Replications: Active Directory replication health
  • Services: Critical service status
  • Advertising: DC advertisement via DNS
  • FsmoCheck: FSMO role consistency

5. DNS Health Checks

Validates DNS configuration:

  • Tests critical SRV records (_ldap, _kerberos)
  • Verifies DNS zone configuration
  • Runs comprehensive DCDiag DNS tests
  • Checks DNS server responsiveness

6. Time Synchronization

Checks time sync configuration:

  • Verifies PDC Emulator time source
  • Confirms other DCs sync with PDC
  • Identifies time sync issues (Kerberos requires sync within 5 minutes)

7. Event Log Analysis

Scans for critical AD events in the past 7 days:

  • Event 2042: Replication hasn’t occurred recently
  • Event 1311: Smart card certificate issues
  • Event 1645: No writable DCs found
  • Event 2087: DNS lookup failures
  • Event 2088: Replication access denied

Interpreting Results

Overall Status

  • Healthy: No critical issues detected
  • Warning: Minor issues found that should be addressed
  • Critical: Serious issues requiring immediate attention

Common Issues

IssuePossible CauseResolution
Service not runningService crashed or disabledRestart service, check event logs
Replication failureNetwork, DNS, or firewall issueRun repadmin /syncall, check connectivity
DNS SRV records missingNetlogon service issueRestart Netlogon, run ipconfig /registerdns
Time sync errorW32Time misconfiguredReconfigure time source on PDC
DCDiag test failedVarious (check specific test)Review test output, consult KB

Scheduled Health Checks

Create Scheduled Task

Run health checks automatically and email reports:

Lang: powershell
1# Create scheduled task to run weekly
2$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\Test-ADHealth.ps1 -ExportPath C:\Reports\ADHealth.html"
3$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 6am
4$principal = New-ScheduledTaskPrincipal -UserId "DOMAIN\ServiceAccount" -LogonType Password -RunLevel Highest
5
6Register-ScheduledTask -TaskName "AD Health Check" -Action $action -Trigger $trigger -Principal $principal -Description "Weekly Active Directory health check"

Email Reports

Combine with email to send reports to administrators:

Lang: powershell
1$report = "C:\Reports\ADHealth_$(Get-Date -Format 'yyyyMMdd').html"
2.\Test-ADHealth.ps1 -ExportPath $report
3
4Send-MailMessage -From "ad-monitoring@domain.com" `
5                 -To "it-team@domain.com" `
6                 -Subject "Weekly AD Health Report - $(Get-Date -Format 'yyyy-MM-dd')" `
7                 -Body "Please see attached AD health report." `
8                 -Attachments $report `
9                 -SmtpServer "mail.domain.com"

Troubleshooting Common Failures

Replication Failures

Lang: powershell
1# Force replication from all partners
2repadmin /syncall /AdeP
3
4# Check specific replication error
5repadmin /showrepl /errorsonly
6
7# View replication queue
8repadmin /queue

DNS Issues

Lang: cmd
1# Re-register DC DNS records
2ipconfig /registerdns
3
4# Restart Netlogon to recreate SRV records
5net stop netlogon && net start netlogon

Service Failures

Lang: powershell
1# Check service dependencies
2Get-Service -Name NTDS -DependentServices
3
4# Review event logs for service errors
5Get-WinEvent -LogName System | Where-Object {$_.Id -eq 7034 -or $_.Id -eq 7031}

Best Practices

  1. Run Weekly: Schedule automated health checks at least weekly
  2. Monitor Trends: Compare reports over time to identify degradation
  3. Alert on Critical: Set up alerts for critical status results
  4. Document Baseline: Establish baseline health metrics
  5. Test Recovery: Regularly test backup and recovery procedures
  6. Patch Management: Keep DCs updated with latest security patches
  7. Capacity Planning: Monitor disk space, especially NTDS database

See Also

Download

Lang: powershell
1# Download the script
2Invoke-WebRequest -Uri "https://glyph.sh/scripts/Test-ADHealth.ps1" -OutFile "Test-ADHealth.ps1"
3
4# Run basic health check
5.\Test-ADHealth.ps1
6
7# Run with HTML report export
8.\Test-ADHealth.ps1 -ExportPath "C:\Reports\ADHealth.html"