Propósito:
Verificar el estado de mi AD.
Pasos:
#############################################################################
# Script: AD_Health_Fusion_Final.ps1
# Descripcion:
# Script avanzado para
monitorizacion de Active Directory:
# - Ping DC
# - Servicios criticos
(Netlogon, NTDS, DNS)
# - Replicacion REAL (repadmin)
# - Tests DCDIAG clave (Replications, Netlogons, Advertising, FSMOCheck)
# - Dashboard HTML
# - Envio email SOLO si hay
errores
#
# Disenado para entornos
grandes minimizando impacto
#############################################################################
# ==========================
# VARIABLES DEL USUARIO
# ==========================
$SMTPServer =
"smtp01.midominio.com"
$SMTPPort = 25
$From =
"miserver@midominio.com"
$To =
"test@test.com"
$Fecha = Get-Date -Format "yyyy-MM-dd - HH:mm"
$Errores = @()
$Subject = "$Fecha - AD Health Monitor"
$ReportPath = "C:\Temp\AD_Health.html"
# ==========================
# HTML INICIO
# ==========================
$HTML = @"
<html>
<head>
<style>
body { font-family: Arial; }
table { border-collapse: collapse; width: 100%; }
th { background-color: #2F5496; color: white; }
td { border: 1px solid #ccc; padding: 5px; text-align: center; }
.ok { background-color: #C6EFCE; }
.error { background-color: #FFC7CE; }
</style>
</head>
<body>
<h2>AD Health Dashboard v2</h2>
<table>
<tr>
<th>DC</th>
<th>Ping</th>
<th>Netlogon</th>
<th>NTDS</th>
<th>DNS</th>
<th>Repadmin</th>
<th>DCDIAG</th>
</tr>
"@
# ==========================
# OBTENER DCs
# ==========================
$DCs = Get-ADDomainController -Filter * | Select-Object -ExpandProperty
HostName
# ==========================
# FUNCION SERVICIOS
# ==========================
function Get-ServiceState {
param($dc,$name)
try {
$svc = Get-Service -ComputerName
$dc -Name $name -ErrorAction Stop
if ($svc.Status -eq
"Running") {
return
@("OK","ok")
} else {
$Errores
+= "$dc servicio $name STOP"
return
@("STOP","error")
}
} catch {
$Errores += "$dc servicio
$name ERROR"
return
@("ERROR","error")
}
}
# ==========================
# ANALISIS POR DC
# ==========================
foreach ($dc in $DCs) {
# PING
if (Test-Connection $dc -Count 1 -Quiet) {
$PingStatus = "OK";
$PingClass = "ok"
} else {
$PingStatus = "FAIL";
$PingClass = "error"
$Errores += "$dc Ping
FAIL"
}
# SERVICIOS
$Netlogon = Get-ServiceState $dc "Netlogon"
$NTDS = Get-ServiceState $dc
"NTDS"
$DNS = Get-ServiceState
$dc "DNS"
# ==========================
# REPLICACION (REPADMIN REAL)
# ==========================
$rep = repadmin /showrepl $dc | Out-String
if ($rep -match "error|fail") {
$RepStatus = "ERROR"
$RepClass = "error"
$Errores += "$dc Repadmin error"
} else {
$RepStatus = "OK"
$RepClass = "ok"
}
# ==========================
# DCDIAG CLAVE
# ==========================
$dcdiag = dcdiag /s:$dc /test:Replications
/test:Netlogons /test:Advertising /test:FSMOCheck | Out-String
if ($dcdiag -match "failed|error") {
$DCDIAGStatus = "ERROR"
$DCDIAGClass = "error"
$Errores += "$dc DCDIAG error"
} else {
$DCDIAGStatus = "OK"
$DCDIAGClass = "ok"
}
# ==========================
# HTML
# ==========================
$HTML += "<tr>"
$HTML += "<td>$dc</td>"
$HTML += "<td
class='$PingClass'>$PingStatus</td>"
$HTML += "<td
class='$($Netlogon[1])'>$($Netlogon[0])</td>"
$HTML += "<td
class='$($NTDS[1])'>$($NTDS[0])</td>"
$HTML += "<td
class='$($DNS[1])'>$($DNS[0])</td>"
$HTML += "<td
class='$RepClass'>$RepStatus</td>"
$HTML += "<td
class='$DCDIAGClass'>$DCDIAGStatus</td>"
$HTML +=
"</tr>"
}
$HTML +=
"</table>"
# ==========================
# RESUMEN ERRORES
# ==========================
#lo envia solo si sale errores
if ($Errores.Count -gt 0) {
$HTML +=
"<h3>Errores detectados
($($Errores.Count))</h3><ul>"
foreach ($e
in $Errores) {
$HTML += "<li>$e</li>"
}
$HTML += "</ul>"
}
$HTML += "</body></html>"
$HTML | Out-File $ReportPath -Encoding UTF8
# ==========================
# EMAIL SOLO SI ERRORES
# ==========================
if ($Errores.Count -gt 0) {
$Subject = "$Fecha - AD Health Alert -
$($Errores.Count) elementos"
Send-MailMessage -SmtpServer $SMTPServer `
-Port $SMTPPort `
-From $From `
-To $To `
-Subject $Subject `
-Body $HTML `
-BodyAsHtml
}
[] Tarea programada
No funciona con el usuario system, hay que poner con uno con
privilegios en el AD
Lo ideal sería ejecutarlo cada hora y que solo envía si hay errores. Yo lo hago una vez al día porque en principio no tengo problemas de sincronización y durante el día si lo tuviese seguro que tendría algún otro indicador que me alertaría.
Resultado
Mejoras v2
He conseguido que se ejecute con el usuario SYSTEM con los siguiente controles, no son exactamente los mismos pero los suficiente para tener un diagnóstico claro.
y con este nuevo código:
|
##############################
# AD_Health
##############################
$SMTPServer = "smtP.MIDOM.com
$SMTPPort = 25
$From = "YO@MIDOM.com"
$To = "GON@MIDOM.com"
$Fecha = Get-Date -Format "yyyy-MM-dd - HH:mm"
$script:Errores = @()
$ReportPath = "C:\Temp\AD_Health.html"
##############################
# FUNCION DCDIAG
##############################
function Test-DCDiagCheck {
param(
[string]$DC,
[string]$TestName
)
try {
$Output = dcdiag /s:$DC /test:$TestName 2>&1 | Out-String
if ($Output -match "(?i)failed test|fatal|error")
{
$script:Errores += "$DC $TestName ERROR"
return @("ERROR","error")
}
return @("OK","ok")
}
catch
{
$script:Errores += "$DC $TestName EXCEPTION"
return @("ERROR","error")
}
}
##############################
# HTML
##############################
$HTML = @"
<html>
<head>
<style>
body { font-family: Arial; }
table { border-collapse: collapse; width:100%; }
th { background:#2F5496; color:white; }
td { border:1px solid #ccc; padding:5px; text-align:center; }
.ok { background:#C6EFCE; }
.error { background:#FFC7CE; }
</style>
</head>
<body>
<h2>AD Health Dashboard</h2>
<table>
<tr>
<th>DC</th>
<th>Ping</th>
<th>Repadmin</th>
<th>Replications</th>
<th>NetLogons</th>
<th>Advertising</th>
<th>FSMO</th>
<th>SYSVOL</th>
</tr>
"@
##############################
# DCS
##############################
$DCs = Get-ADDomainController -Filter * |
Sort-Object HostName |
Select-Object -ExpandProperty HostName
##############################
# ANALISIS
##############################
foreach ($DC in $DCs)
{
##############################
# PING
##############################
if (Test-Connection -ComputerName $DC -Count 1 -Quiet)
{
$PingStatus = "OK"
$PingClass = "ok"
}
else
{
$PingStatus = "FAIL"
$PingClass = "error"
$script:Errores += "$DC Ping FAIL"
}
##############################
# REPADMIN
##############################
try
{
$RepOutput = repadmin /showrepl $DC 2>&1 | Out-String
if (
$RepOutput -match "(?i)fails" -or
$RepOutput -match "(?i)error" -or
$RepOutput -match "(?i)8453" -or
$RepOutput -match "(?i)1722"
)
{
$RepStatus = "ERROR"
$RepClass = "error"
$script:Errores += "$DC Repadmin ERROR"
}
else
{
$RepStatus = "OK"
$RepClass = "ok"
}
}
catch
{
$RepStatus = "ERROR"
$RepClass = "error"
$script:Errores += "$DC Repadmin EXCEPTION"
}
##############################
# TESTS DCDIAG
##############################
$Replications = Test-DCDiagCheck $DC "Replications"
$NetLogons = Test-DCDiagCheck $DC "NetLogons"
$Advertising = Test-DCDiagCheck $DC "Advertising"
$FSMO = Test-DCDiagCheck $DC "FSMOCheck"
$SYSVOL = Test-DCDiagCheck $DC "SysVolCheck"
##############################
# HTML
##############################
$HTML += "<tr>"
$HTML += "<td>$DC</td>"
$HTML += "<td class='$PingClass'>$
$HTML += "<td class='$RepClass'>$RepStatus</
$HTML += "<td class='$($Replications[1])'>$(
$HTML += "<td class='$($NetLogons[1])'>$($
$HTML += "<td class='$($Advertising[1])'>$($
$HTML += "<td class='$($FSMO[1])'>$($FSMO[0]
$HTML += "<td class='$($SYSVOL[1])'>$($
$HTML += "</tr>"
}
##############################
# RESUMEN
##############################
$HTML += "</table>"
if ($script:Errores.Count -gt 0)
{
$HTML += "<h3>Errores detectados ($($script:Errores.Count))</
$HTML += "<ul>"
foreach ($ErrorItem in $script:Errores)
{
$HTML += "<li>$ErrorItem</li>"
}
$HTML += "</ul>"
}
else
{
$HTML += "<h3 style='color:green'>Sin errores detectados</h3>"
}
$HTML += "</body></html>"
##############################
# GUARDAR
##############################
New-Item -ItemType Directory -Path "C:\Temp" -Force | Out-Null
$HTML | Out-File $ReportPath -Encoding UTF8
##############################
# MAIL
##############################
$Subject = "$Fecha - AD Health Report v9 - $($script:Errores.Count) elementos"
Send-MailMessage `
-SmtpServer $SMTPServer `
-Port $SMTPPort `
-From $From `
-To $To `
-Subject $Subject `
-Body $HTML `
-BodyAsHtml |
Mola!!
by GoN | Published: Jun 2026 | Last Updated: Jul 2026