If you’re a Domain Admin responsible for maintaining the health of your Active Directory environment, running dcdiag and repadmin commands daily can be time-consuming. To simplify this routine task, I’ve created a PowerShell script that automates these checks and generates a clear, HTML-based report. This makes daily AD monitoring faster, easier, and far more efficient — a real time-saver for any IT admin
Pre-requisites
- GMSA Account to run the Scheduled Tasks
- Email address and SMTP Address
Please fill the following according to your environment
- $smtphost – SMTP Host of your Domain
- $from – the email address which is going to be used to send emails
- $email1 – the email address which is going to recieve the emails
###################################################################################################################################
# Author: Karanth
# Modified : 19/6/2025
# Satus: DCdiag Test(Replication,sysvol,Services),CPU Utilization,Memory utilization,Lsass Handle Count,LDAP Service Status
# Description: AD Health Status
####################################################################################################################################
###########################Define Variables#########################################################################################
$reportpath = ".\ADReport.htm"
if((test-path $reportpath) -like $false)
{
new-item $reportpath -type file
}
$smtphost = "to be added"
$from = "to be added"
$email1 = "to be added"
$timeout = "60"
###############################HTml Report Content############################
$report = $reportpath
Clear-Content $report
Add-Content $report "<html>"
Add-Content $report "<head>"
Add-Content $report "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $report '<title>AD Status Report</title>'
add-content $report '<STYLE TYPE="text/css">'
add-content $report "<!--"
add-content $report "td {"
add-content $report "font-family: Calibri;"
add-content $report "font-size: 13px;"
add-content $report "border-top: 1px solid #999999;"
add-content $report "border-right: 1px solid #999999;"
add-content $report "border-bottom: 1px solid #999999;"
add-content $report "border-left: 1px solid #999999;"
add-content $report "padding-top: 0px;"
add-content $report "padding-right: 0px;"
add-content $report "padding-bottom: 0px;"
add-content $report "padding-left: 0px;"
add-content $report "}"
add-content $report "body {"
add-content $report "margin-left: 5px;"
add-content $report "margin-top: 5px;"
add-content $report "margin-right: 0px;"
add-content $report "margin-bottom: 10px;"
add-content $report ""
add-content $report "table {"
add-content $report "border: thin solid #000000;"
add-content $report "}"
add-content $report "-->"
add-content $report "</style>"
Add-Content $report "</head>"
Add-Content $report "<body>"
add-content $report "<table width='100%'>"
add-content $report "<tr bgcolor='#DF0101'>"
add-content $report "<td colspan='7' height='25' align='center'>"
add-content $report "<font face='Calibri' color='white' size='4'><strong>Active Directory Health Check</strong></font>"
add-content $report "</td>"
add-content $report "</tr>"
add-content $report "</table>"
add-content $report "<table width='100%'>"
Add-Content $report "<tr bgcolor='#0B0B3B' height='30'>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Domain Controller</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Netlogons Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Replication Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Advertising Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>FSMOCheck Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>KCCCheck Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>DFSRCheck Test</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Ldap service Status(TCP)</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Lsass Handle Count</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>CPU Utilization %</B></td>"
Add-Content $report "<td width='9%' align='center' style='color:white'><B>Memory utilization %</B></td>"
Add-Content $report "</tr>"
#####################################Get ALL DC Servers#################################
Import-module ActiveDirectory
$getForest = [system.directoryservices.activedirectory.Forest]::GetCurrentForest()
$DC = $getForest.domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}
###################################Ping Test##############################################
$Identity = $DC
Add-Content $report "<tr>"
if ( Test-Connection -ComputerName $DC -Count 1 -ErrorAction SilentlyContinue ) {
Write-Host $DC `t $DC `t Ping Success -ForegroundColor Green
Add-Content $report "<td bgcolor= 'GainsBoro' align=center> <B> $Identity</B></td>"
####################Netlogons status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:netlogons /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t Netlogons Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>NetlogonsTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
if($cmp::instr($sysvol1, "passed test NetLogons"))
{
Write-Host $DC `t Netlogons Test passed -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>Netlogons Passed</B></td>"
}
else
{
Write-Host $DC `t Netlogons Test Failed -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>Netlogons Fail</B></td>"
}
}
####################Replications status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:Replications /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t Replications Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>ReplicationsTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
if($cmp::instr($sysvol1, "passed test Replications"))
{
Write-Host $DC `t Replications Test passed -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>Replications Passed</B></td>"
}
else
{
Write-Host $DC `t Replications Test Failed -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>Replications Fail</B></td>"
}
}
####################Advertising status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:Advertising /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t Advertising Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>AdvertisingTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
if($cmp::instr($sysvol1, "passed test Advertising"))
{
Write-Host $DC `t Advertising Test passed -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>Advertising Passed</B></td>"
}
else
{
Write-Host $DC `t Advertising Test Failed -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>Advertising Fail</B></td>"
}
}
####################FSMOCheck status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:FSMOCheck /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t FSMOCheck Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>FSMOCheckTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
$outputText = ($sysvol1 -join " ") -replace '\s+', ' ' # Normalize for multiline match
if ($outputText -match "passed test FsmoCheck") {
Write-Host "$DC`tFSMOCheck Test passed" -ForegroundColor Green
Add-Content $report "<td bgcolor='Aquamarine' height='25' align='center'><b>FSMOCheck Passed</b></td>"
} else {
Write-Host "$DC`tFSMOCheck Test Failed" -ForegroundColor Red
Add-Content $report "<td bgcolor='Red' height='25' align='center'><b>FSMOCheck Fail</b></td>"
}
}
####################KCCheck status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:KccEvent /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t KccEvent Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>KccEventTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
if($cmp::instr($sysvol1, "passed test KccEvent"))
{
Write-Host $DC `t KccEvent Test passed -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>KccEvent Passed</B></td>"
}
else
{
Write-Host $DC `t KccEvent Test Failed -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>KccEvent Fail</B></td>"
}
}
####################DFSREvent status##################
add-type -AssemblyName microsoft.visualbasic
$cmp = "microsoft.visualbasic.strings" -as [type]
$sysvol = start-job -scriptblock {dcdiag /test:DFSREvent /s:$($args[0])} -ArgumentList $DC
wait-job $sysvol -timeout $timeout
if($sysvol.state -like "Running")
{
Write-Host $DC `t DFSREvent Test TimeOut -ForegroundColor Yellow
Add-Content $report "<td bgcolor= 'Yellow' align=center><B>DFSREventTimeout</B></td>"
stop-job $sysvol
}
else
{
$sysvol1 = Receive-job $sysvol
if($cmp::instr($sysvol1, "passed test DFSREvent"))
{
Write-Host $DC `t DFSREvent Test passed -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>DFSREvent Passed</B></td>"
}
else
{
Write-Host $DC `t DFSREvent Test Failed -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>DFSREvent Fail</B></td>"
}
}
####################LDAP Service status(TCP)##################
PortQry.exe -n $DC -p tcp -e 389 > C:\Script\results.txt
$value = get-content -path C:\script\results.txt | where-object {$_ -like "*LISTENING*"}
$split1 = $value.trim(":")
$split2 = $split1.Split(":")[1]
$LDAPServiceStatus = $split2.trim()
if ($LDAPServiceStatus -eq "LISTENING")
{
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>$LDAPServiceStatus</B></td>"
}
else
{
Add-Content $report "<td bgcolor= 'Yellow' height='25' align=center><B>$LDAPServiceStatus</B></td>"
}
####################################Lsass handlecount,CPu,Memory utilization #################################
#$Result = @()
$Lsass = get-process -computername $DC lsass | format-list | findstr "Handles"; $Lsass2 = $Lsass.Split(":")[1]
$Lsass_Count = $Lsass2.trim()
$AVGProc = Get-WmiObject -computername $DC win32_processor | Measure-Object -property LoadPercentage -Average | Select Average
$OS = gwmi -Class win32_operatingsystem -computername $DC |
Select-Object @{Name = "MemoryUsage"; Expression = {“{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize) }}
$CPULoad = "$($AVGProc.Average)%"
$MemLoad = "$($OS.MemoryUsage)%"
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>$Lsass_Count</B></td>"
If ($entry.cpuload -ge 80 -or ($entry.memload -ge 80))
{
Write-Host $DC `t $CPULoad -ge 80 -ForegroundColor Red
Write-Host $DC `t $MemLoad -ge 80 -ForegroundColor Red
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>$CPULoad</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center><B>$MemLoad</B></td>"
}
ElseIf ($entry.cpuload -lt 80 -or ($entry.memload -lt 80))
{
write-Host $DC `t $CPULoad -lt 80 -ForegroundColor Green
write-Host $DC `t $MemLoad -lt 80 -ForegroundColor Green
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>$CPULoad</B></td>"
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>$MemLoad</B></td>"
}
##################################################################################################
}
else
{
Write-Host $DC `t $DC `t Ping Fail -ForegroundColor Red
Add-Content $report "<td bgcolor= 'GainsBoro' align=center> <B> $Identity</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Netlogons Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Replications Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Advertising Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>FSMOCheck Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>KccEvent Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>DFSRCheck Fail</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Not Captured</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Not Captured</B></td>"
Add-Content $report "<td bgcolor= 'Red' height='25' align=center> <B>Not Captured</B></td>"
}
}
Add-Content $report "</tr>"
############################################Close HTMl Tables###########################
Add-content $report "</table>"
Add-Content $report "</body>"
Add-Content $report "</html>"
########################################################################################
#############################################Send Email#################################
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-Content .\ADreport.htm "<BR>"
Add-content $report "<font face='Calibri' Size='3'>"
Add-Content .\ADreport.htm "<h3>Explanation for Healthcheck Parameters</h3>"
add-content .\ADreport.htm "<table font face='Calibri' Size='3' width='90%'>"
add-content .\ADreport.htm "<tr><td height='20' width='10%'><b>Parameter</b></td><td><b>Explanation</b></td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>Netlogon Test</td><td>This will verify that the proper permissions are set for SYSVOL replication </td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>Replication Test</td><td>This test is to monitor the replication</td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>Advertising Test</td><td>This Checks whether domain controller advertises itself in the roles that it should be capable of performing. This test fails if the Netlogon Service has stopped or failed to start</td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>FSMOCheckTest</td><td>This Checks that the domain controller can contact a Kerberos Key Distribution Center (KDC), a time server, a preferred time server, a primary domain controller (PDC), and a global catalog server</td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>KCCheckTest</td><td>This Checks that the KCC is completing without errors</td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>DFSREventTest</td><td>This Checks to see if there are any errors in the file replication systems</td></tr>"
add-content .\ADreport.htm "<tr><td height='20'>Lsass Handlecount </td><td>This Gets the number of handles opened by the Lsass process</td></tr>"
add-content .\ADreport.htm "</table>"
Add-content $report "</font>"
$subject = "Daily Active Directory Health and Performance Report"
$body = Get-Content ".\ADreport.htm"
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage
$msg.To.Add($email1)
$msg.from = $from
$msg.subject = $subject
$msg.body = $body
$msg.isBodyhtml = $true
$smtp.send($msg)
########################################################################################
########################################################################################