ANAVEM
Reference
Languagefr
How to Monitor Active Directory Health with PowerShell Scripts

How to Monitor Active Directory Health with PowerShell Scripts

Create automated health monitoring for Active Directory Domain Controllers using PowerShell scripts, scheduled reports, and email notifications for proactive AD infrastructure management.

Emanuel DE ALMEIDAEmanuel DE ALMEIDA
March 17, 2026 15 min 10
mediumactive-directory 8 steps 15 min

Why Monitor Active Directory Health with PowerShell?

Active Directory is the backbone of most Windows enterprise environments, managing authentication, authorization, and directory services for thousands of users and computers. When AD fails, entire business operations can grind to a halt. Traditional monitoring often relies on reactive approaches - waiting for users to report issues or checking logs after problems occur.

PowerShell-based health monitoring transforms this reactive approach into a proactive strategy. By automating comprehensive checks across domain controllers, replication status, DNS functionality, and critical services, you can identify and resolve issues before they impact users. The Get-ADHealth.ps1 script from ALI TAJRAN provides a robust foundation, performing DCDiag tests, ping checks, DNS validation, and service monitoring while generating color-coded HTML reports.

What Will You Achieve with Automated AD Monitoring?

This tutorial guides you through implementing a complete AD health monitoring solution using PowerShell scripts. You'll learn to configure automated daily and weekly health checks, set up email notifications for critical issues, and create centralized logging for historical analysis. The monitoring system includes custom functions for specific AD components like SYSVOL replication and FSMO role validation.

By the end of this tutorial, you'll have a scheduled monitoring system that runs automatically, sends alerts when issues arise, and provides both detailed reports and a visual dashboard for quick status overview. This proactive approach helps maintain AD infrastructure reliability and reduces the mean time to resolution for directory service issues.

Related: How to Disable NTLM Authentication Protocol in Active

Related: How to Configure LDAPS Protocol in Active Directory 2026

Related: Enable Active Directory Recycle Bin on Windows Server 2022

Related: How to Bulk Import Active Directory Users from CSV Using

Implementation Guide

Full Procedure

01

Install Active Directory PowerShell Module

First, ensure the Active Directory PowerShell module is installed on your domain controller. This module provides the cmdlets needed for AD health monitoring.

Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

If you're running this on a Windows 10/11 client machine instead of a server, use this alternative command:

Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

Verify the module is installed and available:

Get-Module -Name ActiveDirectory -ListAvailable
Pro tip: The ActiveDirectory module is automatically installed on domain controllers, but you'll need to install it manually on member servers or client machines.
02

Download and Prepare the AD Health Check Script

Download the comprehensive Get-ADHealth.ps1 script from ALI TAJRAN's repository. This script performs DCDiag tests, ping checks, DNS validation, and service monitoring.

# Create scripts directory
New-Item -Path "C:\scripts" -ItemType Directory -Force

# Download the script (replace with actual download method)
Invoke-WebRequest -Uri "https://www.alitajran.com/active-directory-health-check-powershell-script/" -OutFile "C:\scripts\Get-ADHealth.ps1"

Unblock the downloaded script to prevent execution policy issues:

Unblock-File -Path "C:\scripts\Get-ADHealth.ps1"

Set the execution policy to allow script execution:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

Verify the script is ready to run:

Get-Content "C:\scripts\Get-ADHealth.ps1" | Select-Object -First 10
Warning: Always review downloaded scripts before execution. Examine the code to understand what it does and ensure it's from a trusted source.
03

Run Basic AD Health Check

Execute your first health check to test the script functionality and generate a baseline report. This will check all domain controllers in your forest.

# Navigate to scripts directory
Set-Location "C:\scripts"

# Run basic health check with HTML report
.\Get-ADHealth.ps1 -ReportFile

For a specific domain only:

.\Get-ADHealth.ps1 -DomainName "yourdomain.com" -ReportFile

The script generates an HTML report with a timestamp. Check the output:

# List generated reports
Get-ChildItem -Path "C:\scripts" -Filter "dc_health_report_*.html" | Sort-Object LastWriteTime -Descending

Open the latest report to review the results:

# Open the most recent report
$latestReport = Get-ChildItem -Path "C:\scripts" -Filter "dc_health_report_*.html" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
Invoke-Item $latestReport.FullName
Pro tip: The HTML report uses color coding - green for passed tests, red for failures, and yellow for warnings. Focus on red items first as they indicate critical issues.
04

Configure Email Notifications

Modify the script to send automated email reports. Open the Get-ADHealth.ps1 file and locate the SMTP settings section, then customize it for your environment.

# Edit the script to configure SMTP settings
$smtpsettings = @{
    To = 'admin@yourdomain.com'
    From = 'adhealth@yourdomain.com'
    Subject = "AD Health Report - $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
    SmtpServer = "mail.yourdomain.com"
    Port = "25"
    # Credential = (Get-Credential)  # Uncomment for authentication
    # UseSsl = $true                 # Uncomment for SSL
}

Test email functionality before scheduling:

# Test email sending
Send-MailMessage -To "admin@yourdomain.com" -From "adhealth@yourdomain.com" -Subject "AD Health Test" -Body "Test email from AD health monitoring" -SmtpServer "mail.yourdomain.com"

Run the script with email notification:

.\Get-ADHealth.ps1 -DomainName "yourdomain.com" -SendEmail

Verify email was sent by checking your inbox and the PowerShell output for any error messages.

Warning: Store SMTP credentials securely. Consider using a dedicated service account with minimal privileges for sending monitoring emails.
05

Create Custom Health Check Functions

Enhance monitoring by adding custom functions for specific AD components. Create a supplementary script for additional checks.

# Create custom AD health functions
function Test-ADReplication {
    param([string]$DomainController)
    
    $replStatus = repadmin /replsummary $DomainController
    $errors = $replStatus | Where-Object { $_ -match "error" }
    
    return @{
        DC = $DomainController
        HasErrors = ($errors.Count -gt 0)
        ErrorCount = $errors.Count
        Details = $replStatus
    }
}

function Test-SysvolReplication {
    $sysvolPath = "\\$env:COMPUTERNAME\SYSVOL"
    $accessible = Test-Path $sysvolPath
    
    return @{
        Path = $sysvolPath
        Accessible = $accessible
        LastWrite = if ($accessible) { (Get-Item $sysvolPath).LastWriteTime } else { "N/A" }
    }
}

function Test-ADServices {
    $services = @("ADWS", "DNS", "DFS Replication", "Intersite Messaging", "Kerberos Key Distribution Center", "NetLogon", "Active Directory Domain Services")
    $results = @()
    
    foreach ($service in $services) {
        $svc = Get-Service -DisplayName "*$service*" -ErrorAction SilentlyContinue
        if ($svc) {
            $results += @{
                ServiceName = $svc.DisplayName
                Status = $svc.Status
                StartType = $svc.StartType
            }
        }
    }
    return $results
}

Save these functions to a separate file and test them:

# Save functions to file
$functions | Out-File "C:\scripts\AD-CustomFunctions.ps1"

# Load and test functions
. "C:\scripts\AD-CustomFunctions.ps1"

# Test replication
Test-ADReplication -DomainController $env:COMPUTERNAME

# Test SYSVOL
Test-SysvolReplication

# Test services
Test-ADServices
Pro tip: Create modular functions for specific checks. This makes troubleshooting easier and allows you to run individual tests when investigating specific issues.
06

Schedule Automated Health Checks

Set up Windows Task Scheduler to run health checks automatically. This ensures consistent monitoring without manual intervention.

# Create scheduled task for daily health checks
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File 'C:\scripts\Get-ADHealth.ps1' -ReportFile -DomainName 'yourdomain.com'"

$trigger = New-ScheduledTaskTrigger -Daily -At "02:00AM"

$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable

$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest

Register the scheduled task:

Register-ScheduledTask -TaskName "AD-HealthCheck-Daily" -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "Daily Active Directory health monitoring"

Create a weekly comprehensive check with email:

# Weekly comprehensive check with email
$weeklyAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File 'C:\scripts\Get-ADHealth.ps1' -SendEmail -DomainName 'yourdomain.com'"

$weeklyTrigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 -DaysOfWeek Monday -At "06:00AM"

Register-ScheduledTask -TaskName "AD-HealthCheck-Weekly-Email" -Action $weeklyAction -Trigger $weeklyTrigger -Settings $settings -Principal $principal -Description "Weekly AD health check with email notification"

Verify scheduled tasks are created:

Get-ScheduledTask -TaskName "AD-HealthCheck*" | Format-Table TaskName, State, NextRunTime
Warning: Run scheduled tasks with appropriate service account permissions. The SYSTEM account works for local checks, but domain-specific operations might require a domain service account.
07

Set Up Centralized Logging and Alerting

Create a centralized logging system to track health check results over time and implement alerting for critical issues.

# Create centralized logging function
function Write-ADHealthLog {
    param(
        [string]$Message,
        [string]$Level = "INFO",
        [string]$LogPath = "C:\logs\ADHealth.log"
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    
    # Ensure log directory exists
    $logDir = Split-Path $LogPath -Parent
    if (!(Test-Path $logDir)) {
        New-Item -Path $logDir -ItemType Directory -Force
    }
    
    # Write to log file
    Add-Content -Path $LogPath -Value $logEntry
    
    # Also write to event log for critical issues
    if ($Level -eq "ERROR" -or $Level -eq "CRITICAL") {
        Write-EventLog -LogName "Application" -Source "AD Health Monitor" -EventId 1001 -EntryType Error -Message $Message
    }
}

Create an alerting function for critical issues:

function Send-ADHealthAlert {
    param(
        [string]$AlertMessage,
        [string]$Severity = "High",
        [array]$Recipients = @("admin@yourdomain.com")
    )
    
    $subject = "[AD ALERT - $Severity] Active Directory Health Issue"
    $body = @"
Active Directory Health Alert

Severity: $Severity
Timestamp: $(Get-Date)
Domain Controller: $env:COMPUTERNAME

Issue Details:
$AlertMessage

Please investigate immediately.
"@
    
    try {
        Send-MailMessage -To $Recipients -From "adalert@yourdomain.com" -Subject $subject -Body $body -SmtpServer "mail.yourdomain.com"
        Write-ADHealthLog "Alert sent successfully: $AlertMessage" "INFO"
    }
    catch {
        Write-ADHealthLog "Failed to send alert: $($_.Exception.Message)" "ERROR"
    }
}

Integrate logging into your health checks:

# Example integration with DCDiag results
$dcdiagResults = dcdiag /test:DNS /test:FSMOCheck /v

if ($dcdiagResults -match "failed") {
    $failedTests = $dcdiagResults | Where-Object { $_ -match "failed" }
    $alertMessage = "DCDiag tests failed:`n" + ($failedTests -join "`n")
    
    Write-ADHealthLog $alertMessage "ERROR"
    Send-ADHealthAlert -AlertMessage $alertMessage -Severity "High"
}
else {
    Write-ADHealthLog "All DCDiag tests passed" "INFO"
}

Test the logging and alerting system:

# Test logging
Write-ADHealthLog "Test log entry" "INFO"

# Test alerting
Send-ADHealthAlert -AlertMessage "Test alert message" -Severity "Low"

# Verify log file
Get-Content "C:\logs\ADHealth.log" -Tail 5
Pro tip: Set up log rotation to prevent log files from growing too large. Use PowerShell to archive logs older than 30 days automatically.
08

Create Performance Monitoring Dashboard

Build a simple HTML dashboard that displays current AD health status and historical trends. This provides a quick visual overview of your AD infrastructure.

# Create dashboard generation function
function New-ADHealthDashboard {
    param(
        [string]$OutputPath = "C:\scripts\dashboard.html",
        [int]$DaysHistory = 7
    )
    
    # Get current domain controllers
    $domainControllers = Get-ADDomainController -Filter * | Select-Object Name, IPv4Address, OperatingSystem, IsGlobalCatalog
    
    # Get recent health check results
    $recentReports = Get-ChildItem "C:\scripts" -Filter "dc_health_report_*.html" | 
        Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-$DaysHistory) } |
        Sort-Object LastWriteTime -Descending
    
    # Generate HTML dashboard
    $html = @"



    Active Directory Health Dashboard
    


    

Active Directory Health Dashboard

Last Updated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')

Domain Controllers Overview

"@ foreach ($dc in $domainControllers) { $pingResult = Test-Connection -ComputerName $dc.Name -Count 1 -Quiet $status = if ($pingResult) { "Online" } else { "Offline" } $html += "" } $html += @"
NameIP AddressOperating SystemGlobal CatalogStatus
$($dc.Name)$($dc.IPv4Address)$($dc.OperatingSystem)$($dc.IsGlobalCatalog)$status

Recent Health Reports

    "@ foreach ($report in $recentReports) { $html += "
  • $($report.Name) - $(($report.LastWriteTime).ToString('yyyy-MM-dd HH:mm'))
  • " } $html += @"

Quick Metrics

Total DCs: $($domainControllers.Count)

Global Catalogs: $(($domainControllers | Where-Object IsGlobalCatalog).Count)

Recent Reports: $($recentReports.Count)

"@ $html | Out-File -FilePath $OutputPath -Encoding UTF8 Write-Host "Dashboard created: $OutputPath" }

Generate and view the dashboard:

# Create the dashboard
New-ADHealthDashboard

# Open dashboard in browser
Invoke-Item "C:\scripts\dashboard.html"

Schedule dashboard updates:

# Add dashboard generation to scheduled task
$dashboardAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -Command 'New-ADHealthDashboard'"

$dashboardTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Hours 1)

Register-ScheduledTask -TaskName "AD-Dashboard-Update" -Action $dashboardAction -Trigger $dashboardTrigger -Settings $settings -Principal $principal
Pro tip: Host the dashboard on a web server or network share so multiple administrators can access it. Consider adding charts using JavaScript libraries for better visualization.

Frequently Asked Questions

How often should I run Active Directory health checks with PowerShell?+
Run basic health checks daily and comprehensive checks weekly. Daily checks should focus on critical services, replication status, and DC availability. Weekly checks can include detailed DCDiag tests, SYSVOL validation, and performance metrics. For high-availability environments, consider running lightweight checks every 4-6 hours with immediate alerting for critical failures.
What are the most important Active Directory health metrics to monitor?+
Monitor domain controller availability (ping/connectivity), replication health between DCs, DNS functionality, critical AD services status (NTDS, DNS, NetLogon), SYSVOL replication, FSMO role holder availability, and authentication response times. Also track event log errors, disk space on DCs, and network connectivity between sites.
Can PowerShell AD health monitoring scripts run on non-domain controller servers?+
Yes, but with limitations. Install the Active Directory PowerShell module (RSAT-AD-PowerShell) on member servers or client machines. Remote monitoring requires appropriate permissions and network connectivity to domain controllers. Some tests like DCDiag work better when run directly on DCs, while others like replication monitoring can be performed remotely.
How do I troubleshoot PowerShell execution policy errors when running AD health scripts?+
Use 'Set-ExecutionPolicy RemoteSigned -Scope CurrentUser' to allow locally created and signed remote scripts. For downloaded scripts, run 'Unblock-File' first. In scheduled tasks, use '-ExecutionPolicy Bypass' parameter. For enterprise environments, configure execution policy via Group Policy to allow signed scripts while maintaining security.
What should I do when PowerShell AD health checks detect replication failures?+
First, run 'repadmin /replsummary' and 'repadmin /showrepl' to identify specific replication partners and errors. Check network connectivity between DCs, verify DNS resolution, and ensure proper time synchronization. Common fixes include restarting the NTDS service, forcing replication with 'repadmin /syncall', or resetting secure channels with 'nltest /sc_reset'. For persistent issues, check event logs for detailed error codes.
Emanuel DE ALMEIDA
Written by

Emanuel DE ALMEIDA

Microsoft MCSA-certified Cloud Architect | Fortinet-focused. I modernize cloud, hybrid & on-prem infrastructure for reliability, security, performance and cost control - sharing field-tested ops & troubleshooting.

Discussion

Share your thoughts and insights

You must be logged in to comment.

Loading comments...