# 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" = "" } If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -gt 1) { $TableOfDCsInADDomainObj."Site Name" = "" } } $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 = "" 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" = "" } If ($DC.OSVersion -ne $null -And $DC.OSVersion -ne "") { $TableOfDCsInADDomainObj."OS Version" = $DC.OSVersion } Else { $TableOfDCsInADDomainObj."OS Version" = "" } $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" = "" } If (($TableOfDCsInADForest | ?{$_."DS Name" -eq $($($DC.Name).Substring(0,$($DC.Name).IndexOf(".")))} | Measure-Object).Count -gt 1) { $TableOfDSServersAObj."Site Name" = "" } } $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 = "" $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