PS: AD Replication Health Checks

4 minute read

Description:

AD health checks are a must have task for Windows Systems Administrators. I set the following first two scripts up that email me every morning at 5 AM and the third script as ran as a continous task on my PDC.

To Resolve:

  1. Copy and paste these scripts to your domain controller. Set as .ps1 files and setup scheduled tasks with them.

 

DC Diag Report:

Begin
{
Import-Module Activedirectory
Function Send-Email ([String] $Body)
{
	$Mailmessage = New-Object System.Net.Mail.Mailmessage
	$Mailmessage.From = "Email@Domain.Com"
	$Mailmessage.To.Add("Administrator@Domain.Com")
	$Mailmessage.Subject = "Dcdiag Health Summary V2"
	$Mailmessage.Body = $Body
	#$Mailmessage.Priority = "High"
	$Mailmessage.Isbodyhtml = $True
	$Smtpclient = New-Object System.Net.Mail.Smtpclient
	$Smtpclient.Host = "Smtp.Server.Hostname"
	$Smtpclient.Send($Mailmessage)
}
Function Converttovertical ([String] $Testname)
{
	$Stringlength = $Testname.Length
	For ($I = 0; $I -Lt $Stringlength; $I++)
	{
		$Newname = $Newname + "<Br>" + $Testname.Substring($I, 1)
	}
	$Newname 
}
}
Process
{    
	
$Adinfo = Get-Addomain
$Alldcs = $Adinfo.Replicadirectoryservers
$Testnamecount = 0
$A = "<Style>"
$A = $A + `
	"Body{Color:#717d7d;Background-Color:#F5f5f5;Font-Size:8pt;Font-Family:'Trebuchet Ms', Helvetica, Sans-Serif;Font-Weight:Normal;Padding-:0px;Margin:0px;Overflow:Auto;}"
#$A = $A + "A{Font-Family:Tahoma;Color:#717d7d;Font-Size:10pt Display: Block;}"
$A = $A + "Table,Td,Th {Font-Family:Tahoma;Color:Black;Font-Size:8pt}"
$A = $A + "Th{Font-Weight:Bold;Background-Color:#Addfff;}"
#$A = $A + "Td {Background-Color:#E3e4fa;Text-Align: Center}"
$A = $A + "</Style>"
Foreach ($Item In $Alldcs)
{
	Dcdiag.Exe /V /S:$Item >> $Logfile
	#New-Variable "Allresults$Item" -Force
	#$C = $Allresults + $Item
	$Allresults = New-Object Object
	$Allresults | Add-Member -Type Noteproperty -Name "Servername" -Value $Item
	#$Testcat = $Null
	$Table += "<Tr><Td>$Item</Td>"
	Get-Content $Logfile | Foreach-Object
	{
		Switch -Regex ($_)
		{
			#"Running"       { $Testcat    = ($_ -Replace ".*Tests On : ").Trim() }
			"Starting"
			{
				$Testname = ($_ -Replace ".*Starting Test: ").Trim() 
			}
			"Passed|Failed"
			{
				If ($_ -Match "Passed")
				{ 
					$Teststatus = "Psd" 
				}
				Else
				{ 
					$Teststatus = "Fld" 
				} 
			}
		}
		If ($Testname -Ne $Null -And $Teststatus -Ne $Null)
		{
			$Testnamevertical = Converttovertical($Testname)
			$Allresults | Add-Member -Name $("$Testnamevertical".Trim()) -Value $Teststatus -Type Noteproperty -Force
			If ($Teststatus -Eq "Fld")
			{
				$Table += "<Td Style=""Background-Color:Red;"">$Teststatus</Td>"
			}
			Else
			{
				$Table += "<Td Style=""Background-Color:Green;"">$Teststatus</Td>"
			}
			If ($Testnamecount -Lt 29)
			{
				$Alltestnames = $Alltestnames + "<Br>" + $Testname
				$Testnames += "<Td Style=""Background-Color:#Cce3ff;"">$Testnamevertical</Td>"
				#$Testnames+="<Td Class=""Titlestyle"">T<Br>E<Br>S<Br>T</Td>"
				$Testnamecount++
			}
			$Testname = $Null; $Teststatus = $Null
		}
		New-Variable "Last$Item" -Force -Value $Allresults
	} 
				
	$Table += "</Tr>"
} 
$Html = `
	"<Html><Head>$A</Head><H2>Active Directory Health Check</H2><Br></Br><Table><Tr><Td>S<Br>E<Br>R<Br>V<Br>E<Br>R<Br>N<Br>A<Br>M<Br>E</Td>" + $Testnames `
	+ "</Tr>" + $Table + "</Table><Br><Br>Tests Ran: $Alltestnames</Html>"
#$Html | Out-File "C:\Scripts\Send-ADDCDiagReport.Html"
$Body = $Html | Out-String
Send-Email $Body
#Log "Email Sent" 
   
}

AD Health Check:

Begin
{
Function Send-Email ([String] $Body)
{
	$Mailmessage = New-Object System.Net.Mail.Mailmessage
	$Mailmessage.From = "Email@Domain.Com"
	$Mailmessage.To.Add("Administratoremail@Domain.Com")
	$Mailmessage.Subject = "Ad Daily Replication Summary"
	$Mailmessage.Body = $Body
	#$Mailmessage.Priority = "High"
	$Mailmessage.Isbodyhtml = $True
	$Smtpclient = New-Object System.Net.Mail.Smtpclient
	$Smtpclient.Host = "Smtp.Server.Hostname"
	$Smtpclient.Send($Mailmessage)
}
}
Process
{
# Get The Replication Info.
$Myrepinfo = @(Repadmin /Replsum * /Bysrc /Bydest /Sort:Delta)
# Initialize Our Array.
$Cleanrepinfo = @()
# Start @ #10 Because All The Previous Lines Are Junk Formatting
# And Strip Off The Last 4 Lines Because They Are Not Needed.
For ($I = 10; $I -Lt ($Myrepinfo.Count - 4); $I++)
{
	If ($Myrepinfo[$I] -Ne "")
	{
		# Remove Empty Lines From Our Array.
		$Myrepinfo[$I] -Replace 'S+', " "           
		$Cleanrepinfo += $Myrepinfo[$I]            
	}
}           
$Finalrepinfo = @()  
Foreach ($Line In $Cleanrepinfo)
{
	$Splitrepinfo = $Line -Split 'S+', 8
	If ($Splitrepinfo[0] -Eq "Source")
	{
		$Reptype = "Source" 
	}
	If ($Splitrepinfo[0] -Eq "Destination")
	{
		$Reptype = "Destination" 
	}
   
	If ($Splitrepinfo[1] -Notmatch "Dsa")
	{      
		# Create An Object And Populate It With Our Values.
		$Objrepvalues = New-Object System.Object
		$Objrepvalues | Add-Member -Type Noteproperty -Name Dsatype -Value $Reptype # Source Or Destination Dsa
		$Objrepvalues | Add-Member -Type Noteproperty -Name Hostname  -Value $Splitrepinfo[1] # Hostname
		$Objrepvalues | Add-Member -Type Noteproperty -Name Delta  -Value $Splitrepinfo[2] # Largest Delta
		$Objrepvalues | Add-Member -Type Noteproperty -Name Fails -Value $Splitrepinfo[3] # Failures
		#$Objrepvalues | Add-Member -Type Noteproperty -Name Slash  -Value $Splitrepinfo[4] # Slash Char
		$Objrepvalues | Add-Member -Type Noteproperty -Name Total -Value $Splitrepinfo[5] # Totals
		$Objrepvalues | Add-Member -Type Noteproperty -Name Pcterror  -Value $Splitrepinfo[6] # % Errors  
		$Objrepvalues | Add-Member -Type Noteproperty -Name Errormsg  -Value $Splitrepinfo[7] # Error Code
  
		# Add The Object As A Row To Our Array   
		$Finalrepinfo += $Objrepvalues
   
	}
}
$Html = $Finalrepinfo|Convertto-Html -Fragment       
   
$Xml = [Xml]$Html
$Attr = $Xml.Createattribute("Id")
$Attr.Value = 'Disktbl'
$Xml.Table.Attributes.Append($Attr)
$Rows = $Xml.Table.Selectnodes('//Tr')
For ($I = 1; $I -Lt $Rows.Count; $I++)
{
	$Value = $Rows.Item($I).Lastchild.'#Text'
	If ($Value -Ne $Null)
	{
		$Attr = $Xml.Createattribute('Style')
		$Attr.Value = 'Background-Color: Red;'
		[Void]$Rows.Item($I).Attributes.Append($Attr)
	}
	Else
	{
		$Value
		$Attr = $Xml.Createattribute('Style')
		$Attr.Value = 'Background-Color: #7bce73;'
		[Void]$Rows.Item($I).Attributes.Append($Attr)
	}
}
#Embed A Css Stylesheet In The Html Header
$Html = $Xml.Outerxml|Out-String
$Style = '<Style Type=Text/Css>#Disktbl { Background-Color: White; } 
	Td, Th { Border:1px Solid Black; Border-Collapse:Collapse; }
	Th { Color:White; Background-Color:Black;Font-Family:Verdana;Font-Size:9pt; }
	Table, Tr, Td { Font-Family:Verdana;Font-Size:9pt;Padding: 1px 5px; }, Th { Padding: 2px 5px; Margin: 0px } Table { Margin-Left:50px; }</Style>'
#Convertto-Html -Head $Style -Body $Html -Title "Replication Report"|Out-File Replicationreport.Htm
$Bodyhtml = Convertto-Html -Head $Style -Body $Html -Title "Replication Report" | Out-String
Send-Email $Bodyhtml
# Log "Email Sent" 
}

Continuous Monitoring:

Begin
{
Function Send-Email ([String] $Body)
{
$Mailmessage = New-Object System.Net.Mail.Mailmessage
$Mailmessage.From = "Email@Domain.Com"
$Mailmessage.To.Add("Administrator@Domain.Com")
$Mailmessage.Subject = "Ad Replication Error!"
$Mailmessage.Body = $Body
$Mailmessage.Priority = "High"
$Mailmessage.Isbodyhtml = $False
$Smtpclient = New-Object System.Net.Mail.Smtpclient
$Smtpclient.Host = "Smtp.Server.Int"
$Smtpclient.Send($Mailmessage)
}
}
Process
{    
$Result = Convertfrom-Csv -Inputobject (Repadmin.Exe /Showrepl * /Csv) | 
Where-Object { $_.Showrepl_Columns -Ne 'Showrepl_Info'} | Out-String
If ($Result -Ne "")
{
Send-Email $Result
Log "Sending Email Due To Replication Issues!" 
}
Else
{
Log "No Replication Issues At This Time" 
}
}

These can be found in my gwActiveDirectory section.