killchain-compendium/Post Exploitation/Windows/Powershell Scripts/Check-SYSVOL-Replication-La...

546 lines
26 KiB
PowerShell
Raw Normal View History

2022-11-11 01:15:07 +01:00
# Abstract: This PoSH Script Checks The SYSVOL Replication Latency/Convergence
# Written By: Jorge de Almeida Pinto [MVP-DS]
# Blog: http://jorgequestforknowledge.wordpress.com/
#
# 2013-03-02: (v0.1): Initial version of the script
# 2014-02-01: (v0.2): Updated to also work on W2K3, added STOP option, added few extra columns to output extra info of DCs, better detection of unavailable DCs, and screen adjustment section added
# 2014-02-09: (v0.3): Solved a bug with regards to the detection/location of RWDCs and RODCs
# 2014-02-11: (v0.4): Added additional logic to determine if a DC is either an RWDC or RODC when it fails using the first logic and changed the layout a little bit
#
# REQUIRES: PowerShell v2.0 or higher
# REQUIRES: At least 2 RWDCs
# SUPPORTS: W2K3(R2), W2K8(R2), W2K12(R2) DCs and most likely higher
# SUPPORTS: NTFRS or DFS-R Replication for the SYSVOL
#
# -----> !!! DISCLAIMER/REMARKS !!! <------
# * The script is freeware, you are free to distribute it, but always refer to this website (http://jorgequestforknowledge.wordpress.com/) as the location where you got it
# * This script is furnished "AS IS". No warranty is expressed or implied!
# * Always test first in lab environment to see if it meets your needs!
# * Use this script at your own risk!
# * I do not warrant this script to be fit for any purpose, use or environment
# * I have tried to check everything that needed to be checked, but I do not guarantee the script does not have bugs.
# * I do not guarantee the script will not damage or destroy your system(s), environment or whatever.
# * I do not accept any liability in any way if you screw up, use the script wrong or in any other way where damage is caused to your environment/systems!
# * If you do not accept these terms do not use the script and delete it immediately!
# -----> !!! DISCLAIMER/REMARKS !!! <------
# Clear The Screen
Clear-Host
# Configure The Appropriate Screen And Buffer Size To Make Sure Everything Fits Nicely
$uiConfig = (Get-Host).UI.RawUI
$uiConfig.WindowTitle = "+++ CHECKING SYSVOL REPLICATION LATENCY/CONVERGENCE +++"
$uiConfig.ForegroundColor = "Yellow"
$uiConfigBufferSize = $uiConfig.BufferSize
$uiConfigBufferSize.Width = 150
$uiConfigBufferSize.Height = 9999
$uiConfigScreenSizeMax = $uiConfig.MaxPhysicalWindowSize
$uiConfigScreenSizeMaxWidth = $uiConfigScreenSizeMax.Width
$uiConfigScreenSizeMaxHeight = $uiConfigScreenSizeMax.Height
$uiConfigScreenSize = $uiConfig.WindowSize
If ($uiConfigScreenSizeMaxWidth -lt 150) {
$uiConfigScreenSize.Width = $uiConfigScreenSizeMaxWidth
} Else {
$uiConfigScreenSize.Width = 150
}
If ($uiConfigScreenSizeMaxHeight -lt 75) {
$uiConfigScreenSize.Height = $uiConfigScreenSizeMaxHeight - 5
} Else {
$uiConfigScreenSize.Height = 75
}
$uiConfig.BufferSize = $uiConfigBufferSize
$uiConfig.WindowSize = $uiConfigScreenSize
# Start...
Write-Host " *******************************************************" -ForeGroundColor Magenta
Write-Host " * *" -ForeGroundColor Magenta
Write-Host " * --> Test SYSVOL Replication Latency/Convergence <-- *" -ForeGroundColor Magenta
Write-Host " * *" -ForeGroundColor Magenta
Write-Host " * Written By: Jorge de Almeida Pinto [MVP-DS] *" -ForeGroundColor Magenta
Write-Host " * (http://jorgequestforknowledge.wordpress.com/) *" -ForeGroundColor Magenta
Write-Host " * *" -ForeGroundColor Magenta
Write-Host " *******************************************************" -ForeGroundColor Magenta
##########
# Some Constants
$continue = $true
$cleanupTempObject = $true
##########
# The Function To Test The Port Connection
Function PortConnectionCheck($fqdnDC,$port,$timeOut) {
$tcpPortSocket = $null
$portConnect = $null
$tcpPortWait = $null
$tcpPortSocket = New-Object System.Net.Sockets.TcpClient
$portConnect = $tcpPortSocket.BeginConnect($fqdnDC,$port,$null,$null)
$tcpPortWait = $portConnect.AsyncWaitHandle.WaitOne($timeOut,$false)
If(!$tcpPortWait) {
$tcpPortSocket.Close()
#Write-Host "Connection Timeout"
Return "ERROR"
} Else {
#$error.Clear()
$ErrorActionPreference = "SilentlyContinue"
$tcpPortSocket.EndConnect($portConnect) | Out-Null
If (!$?) {
#Write-Host $error[0]
Return "ERROR"
} Else {
Return "SUCCESS"
}
$tcpPortSocket.Close()
$ErrorActionPreference = "Continue"
}
}
##########
# Get The FQDN Of The Local AD Domain From The Server This Script Is Executed On
$ADDomainToWriteTo = $(Get-WmiObject -Class Win32_ComputerSystem).Domain
##########
# Get List Of Directory Servers In AD Forest
$ThisADForest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$configNCDN = $ThisADForest.schema.Name.Substring(("CN=Schema,").Length)
$searchRootNTDSdsa = [ADSI]"LDAP://CN=Sites,$configNCDN"
$searcherNTDSdsaRW = New-Object System.DirectoryServices.DirectorySearcher($searchRootNTDSdsa)
$searcherNTDSdsaRO = New-Object System.DirectoryServices.DirectorySearcher($searchRootNTDSdsa)
$searcherNTDSdsaRW.Filter = "(objectCategory=NTDSDSA)"
$searcherNTDSdsaRO.Filter = "(objectCategory=NTDSDSARO)"
$objNTDSdsaRW = $searcherNTDSdsaRW.FindAll()
$objNTDSdsaRO = $searcherNTDSdsaRO.FindAll()
$TableOfRWDCsInADForest = @()
$objNTDSdsaRW | %{
$ntdsDN = $_.Properties.distinguishedname
$nbtRWDCName = $ntdsDN[0].Substring(("CN=NTDS Settings,CN=").Length)
$nbtRWDCName = $nbtRWDCName.Substring(0,$nbtRWDCName.IndexOf(","))
$nbtRWDCSite = $ntdsDN[0].Substring(("CN=NTDS Settings,CN=$nbtRWDCName,CN=Servers,CN=").Length)
$nbtRWDCSite = $nbtRWDCSite.Substring(0,$nbtRWDCSite.IndexOf(","))
$TableOfRWDCsInADForestObj = "" | Select "DS Name","Site Name"
$TableOfRWDCsInADForestObj."DS Name" = $nbtRWDCName
$TableOfRWDCsInADForestObj."Site Name" = $nbtRWDCSite
$TableOfRWDCsInADForest += $TableOfRWDCsInADForestObj
}
$TableOfRODCsInADForest = @()
$objNTDSdsaRO | %{
$ntdsDN = $_.Properties.distinguishedname
$nbtRODCName = $ntdsDN[0].Substring(("CN=NTDS Settings,CN=").Length)
$nbtRODCName = $nbtRODCName.Substring(0,$nbtRODCName.IndexOf(","))
$nbtRODCSite = $ntdsDN[0].Substring(("CN=NTDS Settings,CN=$nbtRODCName,CN=Servers,CN=").Length)
$nbtRODCSite = $nbtRODCSite.Substring(0,$nbtRODCSite.IndexOf(","))
$TableOfRODCsInADForestObj = "" | Select "DS Name","Site Name"
$TableOfRODCsInADForestObj."DS Name" = $nbtRODCName
$TableOfRODCsInADForestObj."Site Name" = $nbtRODCSite
$TableOfRODCsInADForest += $TableOfRODCsInADForestObj
}
$TableOfDCsInADForest = $TableOfRWDCsInADForest + $TableOfRODCsInADForest
##########
# Get List Of DCs In AD Domain, Create And Present In A Table
$contextADDomainToWriteTo = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain",$ADDomainToWriteTo)
$ListOfDCsInADDomain = [System.DirectoryServices.ActiveDirectory.DomainController]::findall($contextADDomainToWriteTo)
$ListOfRWDCsInADDomain = $ListOfDCsInADDomain | ?{$_.InboundConnections -ne $null -and !($_.InboundConnections -match "RODC Connection")}
$ListOfRODCsInADDomain = $ListOfDCsInADDomain | ?{$_.InboundConnections -match "RODC Connection"}
$TableOfDCsInADDomain = @()
Write-Host ""
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------" -ForeGroundColor Cyan
Write-Host "LIST OF DCs IN THE AD DOMAIN '$ADDomainToWriteTo'..." -ForeGroundColor Cyan
ForEach ($DC in $ListOfDCsInADDomain) {
$TableOfDCsInADDomainObj = "" | Select Name,PDC,"Site Name","DS Type","IP Address","OS Version"
$TableOfDCsInADDomainObj.Name = $DC.Name
$TableOfDCsInADDomainObj.PDC = "FALSE"
If ($DC.Roles -ne $null -And $DC.Roles -Contains "PdcRole") {
$TableOfDCsInADDomainObj.PDC = "TRUE"
$pdcFQDN = $DC.Name
$pdcSite = $DC.SiteName
}
If ( $DC.SiteName -ne $null -And $DC.SiteName -ne "") {
$TableOfDCsInADDomainObj."Site Name" = $DC.SiteName
} Else {
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 1) {
$TableOfDCsInADDomainObj."Site Name" = ($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))})."Site Name"
}
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 0) {
$TableOfDCsInADDomainObj."Site Name" = "<Fail>"
}
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -gt 1) {
$TableOfDCsInADDomainObj."Site Name" = "<Fail>"
}
}
$DStype = $null
If ($DStype -eq $null) {
ForEach ($RWDC In $ListOfRWDCsInADDomain) {
If ($RWDC.Name -like $DC.Name) {
$DStype = "Read/Write"
BREAK
}
}
}
If ($DStype -eq $null) {
ForEach ($RODC In $ListOfRODCsInADDomain) {
If ($RODC.Name -like $DC.Name) {
$DStype = "Read-Only"
BREAK
}
}
}
If ($DStype -eq $null) {
$DStype = "<Unknown>"
If (($TableOfRWDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 1) {
$DStype = "Read/Write"
}
If (($TableOfRODCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 1) {
$DStype = "Read-Only"
}
}
$TableOfDCsInADDomainObj."DS Type" = $DStype
If ($DC.IPAddress -ne $null -And $DC.IPAddress -ne "") {
$TableOfDCsInADDomainObj."IP Address" = $DC.IPAddress
} Else {
$TableOfDCsInADDomainObj."IP Address" = "<Fail>"
}
If ($DC.OSVersion -ne $null -And $DC.OSVersion -ne "") {
$TableOfDCsInADDomainObj."OS Version" = $DC.OSVersion
} Else {
$TableOfDCsInADDomainObj."OS Version" = "<Fail>"
}
$TableOfDCsInADDomain += $TableOfDCsInADDomainObj
}
$TableOfDCsInADDomain | FT -AutoSize
Write-Host " --> Found [$($ListOfDCsInADDomain.count)] DC(s) In AD Domain..." -ForeGroundColor Cyan
Write-Host ""
##########
# Specify A RWDC From The Selected AD Domain
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------" -ForeGroundColor Cyan
Write-Host "Which RWDC In The AD Domain '$ADDomainToWriteTo' Should Be Used To Create The Object?" -ForeGroundColor Cyan
Write-Host ""
Write-Host "Available Options Are:" -ForeGroundColor Yellow
Write-Host "[*] Specify 'PDC' To Use The DC With The PDC FSMO Role" -ForeGroundColor Yellow
Write-Host "[*] Just Press Enter To Locate An RWDC" -ForeGroundColor Yellow
Write-Host "[*] Specify The FQDN Of A Specific RWDC" -ForeGroundColor Yellow
Write-Host "[*] Specify 'STOP' To End The Script" -ForeGroundColor Yellow
Write-Host ""
$SourceRWDCInADDomain = Read-Host "Please Choose An Option"
# If PDC Was Specified Find The RWDC With The PDC FSMO Role And Use That
If ($SourceRWDCInADDomain -eq "PDC") {
$SourceRWDCInADDomainFQDN = $pdcFQDN
$SourceRWDCInADDomainSITE = $pdcSite
}
# If Nothing Was Specified Automatically Locate An RWDC To Use
If ($SourceRWDCInADDomain -eq "") {
# Locate Just ONE DC (This Could Be An RWDC Or RODC)
$SourceRWDCInADDomainObjectONE = [System.DirectoryServices.ActiveDirectory.DomainController]::findone($contextADDomainToWriteTo)
# Locate All RWDCs In The AD Domain
$SourceRWDCInADDomainObjectALL = $ListOfRWDCsInADDomain
$UseRWDC = $False
# Check If The Single DC Found Is An RWDC Or Not By Checking If It Is In The List Of RWDCs
ForEach ($RWDC In $SourceRWDCInADDomainObjectALL) {
If ($RWDC.Name -like $SourceRWDCInADDomainObjectONE.Name) {
$UseRWDC = $True
}
}
# If The Single DC Found Is An RWDC, Then Use That One
If ($UseRWDC -eq $True) {
$SourceRWDCInADDomainFQDN = $SourceRWDCInADDomainObjectONE.Name
$SourceRWDCInADDomainSITE = $SourceRWDCInADDomainObjectONE.SiteName
}
# If The Single DC Found Is An RODC, Then Find The RWDC With The PDC FSMO Role And Use That
If ($UseRWDC -eq $False) {
$SourceRWDCInADDomainFQDN = $pdcFQDN
$SourceRWDCInADDomainSITE = $pdcSite
}
}
# If A Specific RWDC Was Specified Then Use That One
If ($SourceRWDCInADDomain -ne "" -And $SourceRWDCInADDomain -ne "PDC" -And $SourceRWDCInADDomain -ne "STOP") {
$contextRWDCToWriteTo = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$SourceRWDCInADDomain)
$SourceRWDCInADDomainObject = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($contextRWDCToWriteTo)
$SourceRWDCInADDomainFQDN = $SourceRWDCInADDomainObject.Name
$SourceRWDCInADDomainSITE = $SourceRWDCInADDomainObject.SiteName
}
# If STOP Was Specified Then End The Script
If ($SourceRWDCInADDomain -eq "STOP") {
Write-Host ""
Write-Host "'STOP' Was Specified..." -ForeGroundColor Red
Write-Host "Aborting Script..." -ForeGroundColor Red
Write-Host ""
EXIT
}
# Check If The Selected DC Actually Exists In The AD Domain And Its Is An RWDC And NOT An RODC
$RWDCvalidity = $False
ForEach ($DC in $ListOfRWDCsInADDomain) {
If ($DC.Name -like $SourceRWDCInADDomainFQDN) {
$RWDCvalidity = $True
}
}
Write-Host ""
Write-Host "Checking Existence And Connectivity Of The Specified RWDC '$SourceRWDCInADDomainFQDN' In The AD Domain '$ADDomainToWriteTo'..." -ForeGroundColor Yellow
If ($RWDCvalidity -eq $True) {
Write-Host ""
Write-Host "The Specified DC '$SourceRWDCInADDomainFQDN' Is An RWDC And It Exists In The AD Domain '$ADDomainToWriteTo'!" -ForeGroundColor Green
Write-Host ""
Write-Host "Continuing Script..." -ForeGroundColor Green
$smbPort = "445"
$timeOut = "500"
$smbConnectionResult = $null
$fqdnDC = $SourceRWDCInADDomainFQDN
$smbConnectionResult = PortConnectionCheck $fqdnDC $smbPort $timeOut
If ($smbConnectionResult -eq "SUCCESS") {
Write-Host ""
Write-Host "The Specified RWDC '$SourceRWDCInADDomainFQDN' Is Reachable!" -ForeGroundColor Green
Write-Host ""
Write-Host "Continuing Script..." -ForeGroundColor Green
Write-Host ""
}
If ($smbConnectionResult -eq "ERROR") {
Write-Host ""
Write-Host "The Specified RWDC '$SourceRWDCInADDomainFQDN' Is NOT Reachable!" -ForeGroundColor Red
Write-Host ""
Write-Host "Please Re-Run The Script And Make Sure To Use An RWDC That Is Reachable!" -ForeGroundColor Red
Write-Host ""
Write-Host "Aborting Script..." -ForeGroundColor Red
Write-Host ""
Break
}
}
If ($RWDCvalidity -eq $False) {
Write-Host ""
Write-Host "The Specified DC '$SourceRWDCInADDomainFQDN' Either Does NOT Exist In The AD Domain '$ADDomainToWriteTo' Or Is NOT And RWDC!" -ForeGroundColor Red
Write-Host ""
Write-Host "Please Re-Run The Script And Provide The FQDN Of An RWDC Within The AD Domain '$ADDomainToWriteTo' That Does Exist" -ForeGroundColor Red
Write-Host ""
Write-Host "Aborting Script..." -ForeGroundColor Red
Write-Host ""
Break
}
##########
# Determine SYSVOL Replication Mechanism And SYSVOL/NetLogon Location On Sourcing RWDC
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------" -ForeGroundColor Cyan
Write-Host "SYSVOL REPLICATION MECHANISM..." -ForeGroundColor Cyan
Write-Host ""
# Get The Default Naming Contexr
$defaultNamingContext = (([ADSI]"LDAP://$SourceRWDCInADDomainFQDN/rootDSE").defaultNamingContext)
# Find The Computer Account Of The Sourcing RWDC
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.Filter = "(&(objectClass=computer)(dNSHostName=$SourceRWDCInADDomainFQDN))"
$Searcher.SearchRoot = "LDAP://" + $SourceRWDCInADDomainFQDN + "/OU=Domain Controllers," + $defaultNamingContext
# The following appears NOT to work on W2K3, but it does upper-level OSes
# $dcObjectPath = $Searcher.FindAll().Path
# The following appears to work on all OSes
$dcObjectPath = $Searcher.FindAll() | %{$_.Path}
# Check If An NTFRS Subscriber Object Exists To Determine If NTFRS Is Being Used Instead Of DFS-R
$SearcherNTFRS = New-Object DirectoryServices.DirectorySearcher
$SearcherNTFRS.Filter = "(&(objectClass=nTFRSSubscriber)(name=Domain System Volume (SYSVOL share)))"
$SearcherNTFRS.SearchRoot = $dcObjectPath
$ntfrsSubscriptionObject = $SearcherNTFRS.FindAll()
If ($ntfrsSubscriptionObject -ne $null) {
Write-Host "SYSVOL Replication Mechanism Being Used...: NTFRS"
# Get The Local Root Path For The SYSVOL
# The following appears NOT to work on W2K3, but it does upper-level OSes
# $sysvolRootPathOnSourcingRWDC = $ntfrsSubscriptionObject.Properties.frsrootpath
# The following appears to work on all OSes
$sysvolRootPathOnSourcingRWDC = $ntfrsSubscriptionObject | %{$_.Properties.frsrootpath}
}
# Check If An DFS-R Subscriber Object Exists To Determine If DFS-R Is Being Used Instead Of NTFRS
$SearcherDFSR = New-Object DirectoryServices.DirectorySearcher
$SearcherDFSR.Filter = "(&(objectClass=msDFSR-Subscription)(name=SYSVOL Subscription))"
$SearcherDFSR.SearchRoot = $dcObjectPath
$dfsrSubscriptionObject = $SearcherDFSR.FindAll()
If ($dfsrSubscriptionObject -ne $null) {
Write-Host "SYSVOL Replication Mechanism Being Used...: DFS-R" -ForeGroundColor Yellow
Write-Host ""
# Get The Local Root Path For The SYSVOL
# The following appears NOT to work on W2K3, but it does not upper-level OSes. NOT really needed, because W2K3 does not support DFS-R for SYSVOL!
# $sysvolRootPathOnSourcingRWDC = $dfsrSubscriptionObject.Properties."msdfsr-rootpath"
# The following appears to work on all OSes
$sysvolRootPathOnSourcingRWDC = $dfsrSubscriptionObject | %{$_.Properties."msdfsr-rootpath"}
}
# Determine The UNC Of The Folder To Write The Temp File To
$scriptsUNCPathOnSourcingRWDC = "\\" + $SourceRWDCInADDomainFQDN + "\" + $($sysvolRootPathOnSourcingRWDC.Replace(":","$")) + "\Scripts"
##########
# Get List Of DCs In AD Domain To Which The Temp Object Will Replicate, Create And Present In A Table
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------" -ForeGroundColor Cyan
Write-Host "LIST OF DIRECTORY SERVERS THE TEMP OBJECT REPLICATES TO..." -ForeGroundColor Cyan
# Put The Selected RWDC Already In the Table [A] Of Directory Servers To Which The Temp Object Will Replicate
$TableOfDSServersA = @()
$TableOfDSServersAObj = "" | Select Name,"Site Name",Reachable
$TableOfDSServersAObj.Name = ("$SourceRWDCInADDomainFQDN [SOURCE RWDC]").ToUpper()
$TableOfDSServersAObj."Site Name" = $SourceRWDCInADDomainSITE
$TableOfDSServersAObj.Reachable = "TRUE"
$TableOfDSServersA += $TableOfDSServersAObj
# Put The Selected RWDC Already In the Table [B] Of Directory Servers Where The Replication Starts
$TableOfDSServersB = @()
$TableOfDSServersBObj = "" | Select Name,"Site Name",Time
$TableOfDSServersBObj.Name = ("$SourceRWDCInADDomainFQDN [SOURCE RWDC]").ToUpper()
$TableOfDSServersBObj."Site Name" = $SourceRWDCInADDomainSITE
$TableOfDSServersBObj.Time = 0.00
$TableOfDSServersB += $TableOfDSServersBObj
# Add All Other Remaining DCs In The Targeted AD Domain To The List Of Directory Servers [A]
ForEach ($DC In $ListOfDCsInADDomain) {
If(!($DC.Name -like $SourceRWDCInADDomainFQDN)) {
$TableOfDSServersAObj = "" | Select Name,"Site Name",Reachable
$TableOfDSServersAObj.Name = $DC.Name
If ($DC.SiteName -ne $null -And $DC.SiteName -ne "") {
$TableOfDSServersAObj."Site Name" = $DC.SiteName
} Else {
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 1) {
$TableOfDSServersAObj."Site Name" = ($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))})."Site Name"
}
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -eq 0) {
$TableOfDSServersAObj."Site Name" = "<Fail>"
}
If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -gt 1) {
$TableOfDSServersAObj."Site Name" = "<Fail>"
}
}
$smbPort = "445"
$timeOut = "500"
$smbConnectionResult = $null
$fqdnDC = $DC.Name
$smbConnectionResult = PortConnectionCheck $fqdnDC $smbPort $timeOut
If ($smbConnectionResult -eq "SUCCESS") {
$TableOfDSServersAObj.Reachable = "TRUE"
}
If ($smbConnectionResult -eq "ERROR") {
$TableOfDSServersAObj.Reachable = "FALSE"
}
$TableOfDSServersA += $TableOfDSServersAObj
}
}
$TableOfDSServersA | FT -AutoSize
Write-Host " --> Found [$($TableOfDSServersA.count)] Directory Server(s)..." -ForeGroundColor Cyan
Write-Host ""
##########
# Create The Temp Object On The Targeted RWDC
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------" -ForeGroundColor Cyan
Write-Host "CREATING TEMP TEXT FILE IN SYSVOL/NETLOGON...:" -ForeGroundColor Cyan
Write-Host ""
$domainNCDN = $defaultNamingContext
$tempObjectName = "sysvolReplTempObject" + (Get-Date -f yyyyMMddHHmmss) + ".txt"
Write-Host " --> On RWDC.............: $SourceRWDCInADDomainFQDN" -ForeGroundColor Yellow
Write-Host " --> With Full Name......: $tempObjectName" -ForeGroundColor Yellow
Write-Host " --> With Contents.......: ...!!!...TEMP OBJECT TO TEST SYSVOL REPLICATION LATENCY/CONVERGENCE...!!!..." -ForeGroundColor Yellow
Write-Host " --> In AD Domain........: $ADDomainToWriteTo ($domainNCDN)" -ForeGroundColor Yellow
"...!!!...TEMP OBJECT TO TEST AD REPLICATION LATENCY/CONVERGENCE...!!!..." | Out-File -FilePath $($scriptsUNCPathOnSourcingRWDC + "\" + $tempObjectName)
Write-Host "`n Temp Text File [$tempObjectName] Has Been Created In The NetLogon Share Of RWDC [$SourceRWDCInADDomainFQDN]! `n" -ForeGroundColor Yellow
##########
# Go Through The Process Of Checking Each Directory Server To See If The Temp Object Already Has Replicated To It
$startDateTime = Get-Date
$i = 0
Write-Host " --> Found [$($TableOfDSServersA.count)] Directory Server(s)..." -ForeGroundColor Yellow
Write-Host ""
While($continue) {
$i++
$oldpos = $host.UI.RawUI.CursorPosition
Write-Host " ====================== CHECK $i ======================" -ForeGroundColor Yellow
Write-Host ""
Write-Host " REMARK: Each DC In The List Below Must Be At Least Accessible Through SMB Over TCP (445)" -ForeGroundColor Red
Write-Host ""
Start-Sleep 1
$replicated = $true
# For Each Directory Server In The List/Table [A] Perform A Number Of Steps
ForEach ($DSsrv in $TableOfDSServersA) {
If ($DSsrv.Name -match $SourceRWDCInADDomainFQDN) {
Write-Host " * Contacting DC In AD domain ...[$($DSsrv.Name.ToUpper())]..." -ForeGroundColor Yellow
Write-Host " - DC Is Reachable..." -ForeGroundColor Green
Write-Host " - Object [$tempObjectName] Exists In The NetLogon Share" (" "*3) -ForeGroundColor Green
continue
}
# If The Directory Server Is A DC In The AD Domain, Then Connect Through LDAP (TCP:445)
If ($DSsrv.Name -notmatch $SourceRWDCInADDomainFQDN) {
Write-Host ""
Write-Host " * Contacting DC In AD domain ...[$($DSsrv.Name.ToUpper())]..." -ForeGroundColor Yellow
$connectionResult = $null
If ($DSsrv.Reachable -eq "TRUE") {
Write-Host " - DC Is Reachable..." -ForeGroundColor Green
$objectPath = "\\" + $($DSsrv.Name) + "\Netlogon\" + $tempObjectName
$connectionResult = "SUCCESS"
}
If ($DSsrv.Reachable -eq "FALSE") {
Write-Host " - DC Is NOT Reachable..." -ForeGroundColor Red
$connectionResult = "FAILURE"
}
}
# If The Connection To The DC Is Successful
If ($connectionResult -eq "SUCCESS") {
If (Test-Path -Path $objectPath) {
# If The Temp Object Already Exists
Write-Host " - Object [$tempObjectName] Now Does Exist In The NetLogon Share" (" "*3) -ForeGroundColor Green
If (!($TableOfDSServersB | ?{$_.Name -match $DSsrv.Name})) {
$TableOfDSServersBobj = "" | Select Name,"Site Name",Time
$TableOfDSServersBobj.Name = $DSsrv.Name
$TableOfDSServersBObj."Site Name" = $DSsrv."Site Name"
$TableOfDSServersBObj.Time = ("{0:n2}" -f ((Get-Date)-$startDateTime).TotalSeconds)
$TableOfDSServersB += $TableOfDSServersBObj
}
} Else {
# If The Temp Object Does Not Yet Exist
Write-Host " - Object [$tempObjectName] Does NOT Exist Yet In The NetLogon Share" -ForeGroundColor Red
$replicated = $false
}
}
# If The Connection To The DC Is Unsuccessful
If ($connectionResult -eq "FAILURE") {
Write-Host " - Unable To Connect To DC/GC And Check For The Temp Object..." -ForeGroundColor Red
If (!($TableOfDSServersB | ?{$_.Name -match $DSsrv.Name})) {
$TableOfDSServersBobj = "" | Select Name,"Site Name",Time
$TableOfDSServersBobj.Name = $DSsrv.Name
$TableOfDSServersBObj."Site Name" = $DSsrv."Site Name"
$TableOfDSServersBObj.Time = "<Fail>"
$TableOfDSServersB += $TableOfDSServersBObj
}
}
}
If ($replicated) {
$continue = $false
} Else {
$host.UI.RawUI.CursorPosition = $oldpos
}
}
##########
# Show The Start Time, The End Time And The Duration Of The Replication
$endDateTime = Get-Date
$duration = "{0:n2}" -f ($endDateTime.Subtract($startDateTime).TotalSeconds)
Write-Host "`n Start Time......: $(Get-Date $startDateTime -format "yyyy-MM-dd HH:mm:ss")" -ForeGroundColor Yellow
Write-Host " End Time........: $(Get-Date $endDateTime -format "yyyy-MM-dd HH:mm:ss")" -ForeGroundColor Yellow
Write-Host " Duration........: $duration Seconds" -ForeGroundColor Yellow
##########
# Delete The Temp Object On The RWDC
If ($cleanupTempObject) {
Write-Host ""
Write-Host " Deleting Temp Text File... `n" -ForeGroundColor Yellow
Remove-Item $($scriptsUNCPathOnSourcingRWDC + "\" + $tempObjectName) -Force
Write-Host " Temp Text File [$tempObjectName] Has Been Deleted On The Target RWDC! `n" -ForeGroundColor Yellow
}
##########
# Output The Table [B] Containing The Information Of Each Directory Server And How Long It Took To Reach That Directory Server After The Creation On The Source RWDC
$TableOfDSServersB | Sort-Object Time | FT -AutoSize