Skip to content

Instantly share code, notes, and snippets.

@zjorz
Last active May 12, 2023 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zjorz/5a74f785bc0ff1f8a96533ba347541b2 to your computer and use it in GitHub Desktop.
Save zjorz/5a74f785bc0ff1f8a96533ba347541b2 to your computer and use it in GitHub Desktop.
Fixing Broken DFS-R Replication Group (SYSVOL) Replication Between All Replication Group Members While Assigning A Primary Member As Source
#-------
# Fixing Broken DFS-R Replication Group Replication Between All Replication Group Members While Assigning A Primary Member As Source
#-------
# ASSUMPTIONS:
# * Name Resolution Works
# * All DCs In The AD Domain Are Available/Up And Running
# * All DCs In The AD Domain Are Reachable For LDAP, ADWS, Remote Management, WMI
# * The Account Used To Execute This Has AT LEAST "Domain Admin" Equivalent Permissions In The AD Domain Being Processed
# * The Content Of The SYSVOL Of The Chosen DC To Be The Primary Member Is Healthy
#--------------------#-----------------------#-----------------------#-----------------------#-----------------------#-----------------------
# dfsrReplGroupPrimaryMemberFQDN = "DCWithPDCFSMO" <- Will Target The DC In The AD Domain With The PDC FSMO Role
# dfsrReplGroupPrimaryMemberFQDN = "<FQDN Of DC In AD Domain>" <- Will Target The Specified DC In The AD Domain
$dfsrParamsCollection = @{actions = @("GET", "DISABLE", "POLLAD", "ENABLE", "POLLAD", "GET"); dfsrReplGroupPrimaryMemberFQDN = "DCWithPDCFSMO" }
#--------------------#-----------------------#-----------------------#-----------------------#-----------------------#-----------------------
Invoke-Command -ArgumentList $dfsrParamsCollection -ScriptBlock {
Param (
$dfsrParamsCollection
)
Clear-Host
Function dfsrStateNrToState {
Param (
$dfsrStateNr
)
Switch ($dfsrStateNr) {
0 { Return 'Uninitialized' }
1 { Return 'Initialized' }
2 { Return 'Initial Sync' }
3 { Return 'Auto Recovery' }
4 { Return 'Normal' }
5 { Return 'In Error' }
Default { Return 'Undetermined/Legacy' }
}
}
### Get Local Computer Domain
$fqdnDomainName = $(Get-WmiObject -Class Win32_ComputerSystem).Domain
# Get Environmental Information
$adRwdcFQDN = ((Get-ADDomainController -DomainName $fqdnDomainName -Discover).HostName)[0]
$adDomain = Get-ADDomain -Server $adRwdcFQDN
$adDomainDN = $adDomain.DistinguishedName
$adRwdcPdcFsmoFQDN = $adDomain.PDCEmulator
$rwdcsInADDomain = $adDomain.ReplicaDirectoryServers
$rodcsInADDomain = $adDomain.ReadOnlyReplicaDirectoryServers
# Get Parameter Details
$actions = $dfsrParamsCollection.actions
$dfsrReplGroupName = "Domain System Volume"
$dfsrReplGroupPrimaryMemberFQDN = If (($dfsrParamsCollection.dfsrReplGroupPrimaryMemberFQDN).ToUpper() -eq "DCWithPDCFSMO") { $adRwdcPdcFsmoFQDN } Else { $($dfsrParamsCollection.dfsrReplGroupPrimaryMemberFQDN) }
# Build The DFS-R Replication Topology Information With All The Members To Process For Each Action
$dfsrTopologyDN = "CN=Topology,CN=$dfsrReplGroupName,CN=DFSR-GlobalSettings,CN=System,$adDomainDN"
$nameToFQDNHT = @{}
$fqdnToCompRefHT = @{}
$dcTypeHT = @{}
Write-Host "=============================================================================================================" -ForegroundColor Magenta
Write-Host "=== WARNING: In Very Large Environments, The Initial Step Of Gathering The Data May Take Some Serious Time===" -ForegroundColor Magenta
Write-Host "=============================================================================================================" -ForegroundColor Magenta
$dfsrGroupTopologyMembers = Get-ADObject -SearchBase $dfsrTopologyDN -SearchScope Subtree -LDAPFilter "(objectClass=msDFSR-Member)"-Properties "msDFSR-ComputerReference", name -Server $adRwdcFQDN
$dfsrGroupTopologyMembers | ForEach-Object {
$dfsrGroupTopologyMember = $null
$dfsrGroupTopologyMember = $_
$dfsrGroupTopologyMemberComputerReference = $null
$dfsrGroupTopologyMemberComputerReference = $dfsrGroupTopologyMember."msDFSR-ComputerReference"
$dfsrGroupTopologyMemberComputerName = $null
$dfsrGroupTopologyMemberComputerName = $dfsrGroupTopologyMemberComputerReference.Substring(3, $dfsrGroupTopologyMemberComputerReference.IndexOf(",") - 3)
$dfsrGroupTopologyMemberComputerDnsFQDN = $null
$dfsrGroupTopologyMemberComputerDnsFQDN = [System.Net.Dns]::GetHostByName($dfsrGroupTopologyMemberComputerName).HostName
$nameToFQDNHT[$dfsrGroupTopologyMemberComputerName] = $dfsrGroupTopologyMemberComputerDnsFQDN
$fqdnToCompRefHT[$dfsrGroupTopologyMemberComputerDnsFQDN] = $dfsrGroupTopologyMemberComputerReference
If ($rwdcsInADDomain -contains $dfsrGroupTopologyMemberComputerDnsFQDN) {
$dcTypeHT[$dfsrGroupTopologyMemberComputerDnsFQDN] = "READWRITE"
} ElseIf ($rodcsInADDomain -contains $dfsrGroupTopologyMemberComputerDnsFQDN) {
$dcTypeHT[$dfsrGroupTopologyMemberComputerDnsFQDN] = "READONLY"
} Else {
$dcTypeHT[$dfsrGroupTopologyMemberComputerDnsFQDN] = "UNKNOWN"
}
}
$dfsrMembersToProcess = $nameToFQDNHT.Count
# For Each Defined Action Process Those Against All DFS-R Members
$actionNr = 0
$actions | ForEach-Object {
$actionNr++
$action = $null
$action = $_
$i = 0
# For Each DFS-R Member Process It As Needed
([array]$nameToFQDNHT.Values) | Sort-Object | ForEach-Object {
$dfsrGroupMemberFQDN = $null
$dfsrGroupMemberFQDN = $_
$i++
If ($action.ToUpper() -eq "POLLAD") {
# Only For The Action 'POLLAD', Have The DFS-R Member Poll AD For The Latest Info
Write-Host "======================== DFS-R Group Member FQDN: $dfsrGroupMemberFQDN ($($i.ToString().PadLeft($($dfsrMembersToProcess.ToString().Length), '0')) Of $dfsrMembersToProcess) ========================" -ForegroundColor Magenta
Write-Host "ACTION.................................: '$($action.ToUpper())'" -ForegroundColor Yellow
Write-Host "DC FQDN................................: $dfsrGroupMemberFQDN" -ForegroundColor Yellow
Write-Host "DC Type................................: $($dcTypeHT[$dfsrGroupMemberFQDN])" -ForegroundColor Yellow
Write-Host "POLLING AD FOR LATEST INFORMATION..." -ForegroundColor Yellow
Invoke-Command -ComputerName $dfsrGroupMemberFQDN -ArgumentList $actions, $actionNr -ScriptBlock {
Param (
$actions,
$actionNr
)
DFSRDIAG POLLAD
# DISABLE: Event ID 4114 The replicated folder at local path D:\AD\SYSVOL\domain has been disabled. The replicated folder will not participate in replication until it is enabled. All data in the replicated folder will be treated as pre-existing data when this replicated folder is enabled.
If ($actions[$actionNr - 2] -eq "DISABLE") {
Start-Sleep -s 5
Try {
Get-WinEvent -LogName "DFS Replication" -FilterXPath "*[System[EventID=4114 and TimeCreated[timediff(@SystemTime) <= 300000]]]" -ErrorAction Stop | Format-List MachineName, TimeCreated, ProviderName, Id, LevelDisplayName, Message
} Catch {
}
}
# ENABLE - NON-AUTH: Event ID 4614 The DFS Replication service initialized SYSVOL at local path D:\AD\SYSVOL\domain and is waiting to perform initial replication
# ENABLE - NON-AUTH: Event ID 4604 The DFS Replication service successfully initialized the SYSVOL replicated folder at local path D:\AD\SYSVOL\domain
# ENABLE - AUTH: Event ID 4602 The DFS Replication service successfully initialized the SYSVOL replicated folder at local path D:\AD\SYSVOL\domain. This member is the designated primary member for this replicated folder
If ($actions[$actionNr - 2] -eq "ENABLE") {
Start-Sleep -s 15
Try {
Get-WinEvent -LogName "DFS Replication" -FilterXPath "*[System[(EventID=4614 or EventID=4604 or EventID=4602) and TimeCreated[timediff(@SystemTime) <= 300000]]]" -ErrorAction Stop | Format-List MachineName, TimeCreated, ProviderName, Id, LevelDisplayName, Message
} Catch {
}
}
}
} Else {
# For Every Other Action, Gather The Info Of The DFS-R Group And Shared Folder
$dfsrGroupTopologyMemberSubscriberDN = $null
$dfsrGroupTopologyMemberSubscriberDN = "CN=$dfsrReplGroupName,CN=DFSR-LocalSettings,$($fqdnToCompRefHT[$dfsrGroupMemberFQDN])"
$dfsrGroupTopologyMemberSubscriptionDN = $null
$dfsrGroupTopologyMemberSubscriptionDN = "CN=SYSVOL Subscription,$dfsrGroupTopologyMemberSubscriberDN"
$dfsrGroupTopologyMemberSubscriptionBefore = $null
$dfsrGroupTopologyMemberSubscriptionBefore = Get-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Properties "msDFSR-RootPath", "msDFSR-Enabled", "msDFSR-Options" -Server $adRwdcFQDN
$dfsrGroupTopologyMemberSubscriptionRootPath = $null
$dfsrGroupTopologyMemberSubscriptionRootPath = $dfsrGroupTopologyMemberSubscriptionBefore."msDFSR-RootPath"
$dfsrGroupTopologyMemberSubscriptionEnabledBefore = $null
$dfsrGroupTopologyMemberSubscriptionEnabledBefore = $dfsrGroupTopologyMemberSubscriptionBefore."msDFSR-Enabled"
$dfsrGroupTopologyMemberSubscriptionOptionsBefore = $null
$dfsrGroupTopologyMemberSubscriptionOptionsBefore = $dfsrGroupTopologyMemberSubscriptionBefore."msDFSR-Options"
$dfsrGroupTopologyMemberSubscriptionLocalReplFolderBefore = $null
$dfsrGroupTopologyMemberSubscriptionLocalReplFolderBefore = Get-WmiObject -ComputerName $dfsrGroupMemberFQDN -Namespace "root\MicrosoftDFS" -Class DfsrReplicatedFolderInfo -Filter "ReplicatedFolderName='SYSVOL Share'"
$dfsrGroupTopologyMemberSubscriptionName = $null
$dfsrGroupTopologyMemberSubscriptionName = $dfsrGroupTopologyMemberSubscriptionLocalReplFolderBefore.ReplicatedFolderName
$dfsrGroupTopologyMemberSubscriptionStateNrBefore = $null
$dfsrGroupTopologyMemberSubscriptionStateNrBefore = $dfsrGroupTopologyMemberSubscriptionLocalReplFolderBefore.State
$dfsrGroupTopologyMemberSubscriptionStateBefore = $null
$dfsrGroupTopologyMemberSubscriptionStateBefore = dfsrStateNrToState $dfsrGroupTopologyMemberSubscriptionStateNrBefore
Write-Host "======================== DFS-R Group Member FQDN: $dfsrGroupMemberFQDN ($($i.ToString().PadLeft($($dfsrMembersToProcess.ToString().Length), '0')) Of $dfsrMembersToProcess) ========================" -ForegroundColor Magenta
Write-Host "ACTION.................................: '$($action.ToUpper())'" -ForegroundColor Yellow
Write-Host "DC FQDN................................: $dfsrGroupMemberFQDN" -ForegroundColor Yellow
Write-Host "DC Type................................: $($dcTypeHT[$dfsrGroupMemberFQDN])" -ForegroundColor Yellow
Write-Host "DFS-R Replication Group Name...........: $dfsrReplGroupName" -ForegroundColor Yellow
Write-Host "DFS-R Replication Domain FQDN..........: $fqdnDomainName" -ForegroundColor Yellow
Write-Host "DFS-R Subscription DN..................: $dfsrGroupTopologyMemberSubscriptionDN" -ForegroundColor Yellow
Write-Host "DFS-R Folder Name......................: $dfsrGroupTopologyMemberSubscriptionName" -ForegroundColor Yellow
Write-Host "DFS-R Folder Root Path.................: $dfsrGroupTopologyMemberSubscriptionRootPath" -ForegroundColor Yellow
Write-Host ""
Write-Host "CURRENT STATE..." -ForegroundColor Cyan
Write-Host " > DFS-R Folder Member Enabled.........: $dfsrGroupTopologyMemberSubscriptionEnabledBefore" -ForegroundColor Yellow
Write-Host " > DFS-R Folder Member Options.........: $dfsrGroupTopologyMemberSubscriptionOptionsBefore" -ForegroundColor Yellow
Write-Host " > DFS-R Folder State..................: $dfsrGroupTopologyMemberSubscriptionStateBefore" -ForegroundColor Yellow
Write-Host ""
If ($action.ToUpper() -eq "DISABLE" -Or $action.ToUpper() -eq "ENABLE") {
If ($action.ToUpper() -eq "DISABLE") {
If ($dfsrGroupMemberFQDN -eq $dfsrReplGroupPrimaryMemberFQDN.ToUpper()) {
If ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READWRITE") {
Write-Host "Disabling And Configuring '$dfsrGroupMemberFQDN' As PRIMARY Member For DFS-R Replication Group '$dfsrReplGroupName' Against '$dfsrGroupMemberFQDN' (Itself)..." -ForegroundColor Yellow
Write-Host ""
Set-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Replace @{"msDFSR-Enabled" = "FALSE"; "msDFSR-Options" = 1 } -Server $dfsrGroupMemberFQDN
} ElseIf ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READONLY") {
Write-Host "Disabling And Configuring '$dfsrGroupMemberFQDN' As PRIMARY Member For DFS-R Replication Group '$dfsrReplGroupName' Against '$adRwdcPdcFsmoFQDN' (The RWDC With The PDC FSMO Role)..." -ForegroundColor Red
Write-Host "Something Is Wrong! - An RODC CANNOT Be The PRIMARY Member Of The SYSVOL!" -ForegroundColor Red
Write-Host ""
EXIT
} Else {
Write-Host "NOT Doing Anything About '$dfsrGroupMemberFQDN' For DFS-R Replication Group '$dfsrReplGroupName' As The DC Type Is Unknown..." -ForegroundColor Red
Write-Host ""
}
Start-Sleep -s 5
} Else {
If ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READWRITE") {
Write-Host "Disabling And Configuring '$dfsrGroupMemberFQDN' As SECONDARY Member For DFS-R Replication Group '$dfsrReplGroupName' Against '$dfsrGroupMemberFQDN' (Itself)..." -ForegroundColor Yellow
Write-Host ""
Set-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Replace @{"msDFSR-Enabled" = "FALSE"; "msDFSR-Options" = 0 } -Server $dfsrGroupMemberFQDN
} ElseIf ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READONLY") {
Write-Host "Disabling And Configuring '$dfsrGroupMemberFQDN' As SECONDARY Member For DFS-R Replication Group '$dfsrReplGroupName' Against '$adRwdcPdcFsmoFQDN' (The RWDC With The PDC FSMO Role)..." -ForegroundColor Yellow
Write-Host ""
Set-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Replace @{"msDFSR-Enabled" = "FALSE"; "msDFSR-Options" = 0 } -Server $adRwdcPdcFsmoFQDN
Try {
Sync-ADObject -Object $dfsrGroupTopologyMemberSubscriptionDN -Source $adRwdcPdcFsmoFQDN -Destination $dfsrGroupMemberFQDN -ErrorAction Stop | Out-Null
} Catch {
REPADMIN /SYNCALL $adRwdcPdcFsmoFQDN $adDomainDN /deP | Out-Null
}
#Start-Sleep -s 5
#Get-ADReplicationPartnerMetadata -Target $dfsrGroupMemberFQDN -Partition Domain | Format-Table LastReplicationAttempt, LastReplicationSuccess, Partner
} Else {
Write-Host "NOT Doing Anything About '$dfsrGroupMemberFQDN' For DFS-R Replication Group '$dfsrReplGroupName' As The DC Type Is Unknown..." -ForegroundColor Red
Write-Host ""
}
}
}
If ($action.ToUpper() -eq "ENABLE") {
If ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READWRITE") {
Write-Host "(Re-)Enabling '$dfsrGroupMemberFQDN' For DFS-R Replication Group '$dfsrReplGroupName' Against '$dfsrGroupMemberFQDN' (Itself)..." -ForegroundColor Yellow
Write-Host ""
Set-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Replace @{"msDFSR-Enabled" = "TRUE" } -Server $dfsrGroupMemberFQDN
} ElseIf ($dcTypeHT[$dfsrGroupMemberFQDN] -eq "READONLY") {
Write-Host "(Re-)Enabling '$dfsrGroupMemberFQDN' For DFS-R Replication Group '$dfsrReplGroupName' Against '$adRwdcPdcFsmoFQDN' (The RWDC With The PDC FSMO Role)..." -ForegroundColor Yellow
Write-Host ""
Set-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Replace @{"msDFSR-Enabled" = "TRUE" } -Server $adRwdcPdcFsmoFQDN
Try {
Sync-ADObject -Object $dfsrGroupTopologyMemberSubscriptionDN -Source $adRwdcPdcFsmoFQDN -Destination $dfsrGroupMemberFQDN -ErrorAction Stop | Out-Null
} Catch {
REPADMIN /SYNCALL $adRwdcPdcFsmoFQDN $adDomainDN /deP | Out-Null
}
#Start-Sleep -s 5
#Get-ADReplicationPartnerMetadata -Target $dfsrGroupMemberFQDN -Partition Domain | Format-Table LastReplicationAttempt, LastReplicationSuccess, Partner
} Else {
Write-Host "NOT Doing Anything About '$dfsrGroupMemberFQDN' For DFS-R Replication Group '$dfsrReplGroupName' As The DC Type Is Unknown..." -ForegroundColor Red
Write-Host ""
}
}
$dfsrGroupTopologyMemberSubscriptionAfter = $null
$dfsrGroupTopologyMemberSubscriptionAfter = Get-ADObject -Identity $dfsrGroupTopologyMemberSubscriptionDN -Properties "msDFSR-Enabled", "msDFSR-Options" -Server $dfsrGroupMemberFQDN
$dfsrGroupTopologyMemberSubscriptionEnabledAfter = $null
$dfsrGroupTopologyMemberSubscriptionEnabledAfter = $dfsrGroupTopologyMemberSubscriptionAfter."msDFSR-Enabled"
$dfsrGroupTopologyMemberSubscriptionOptionsAfter = $null
$dfsrGroupTopologyMemberSubscriptionOptionsAfter = $dfsrGroupTopologyMemberSubscriptionAfter."msDFSR-Options"
$dfsrGroupTopologyMemberSubscriptionLocalReplFolderAfter = $null
$dfsrGroupTopologyMemberSubscriptionLocalReplFolderAfter = Get-WmiObject -ComputerName $dfsrGroupMemberFQDN -Namespace "root\MicrosoftDFS" -Class DfsrReplicatedFolderInfo -Filter "ReplicatedFolderName='SYSVOL Share'"
$dfsrGroupTopologyMemberSubscriptionStateNrAfter = $null
$dfsrGroupTopologyMemberSubscriptionStateNrAfter = $dfsrGroupTopologyMemberSubscriptionLocalReplFolderAfter.State
$dfsrGroupTopologyMemberSubscriptionStateAfter = $null
$dfsrGroupTopologyMemberSubscriptionStateAfter = dfsrStateNrToState $dfsrGroupTopologyMemberSubscriptionStateNrAfter
Write-Host "NEW STATE..." -ForegroundColor Cyan
If ($action.ToUpper() -eq "DISABLE") {
Write-Host " > Primary Member......................: $(If ($dfsrGroupMemberFQDN -eq $dfsrReplGroupPrimaryMemberFQDN.ToUpper()) {"TRUE"} Else {"FALSE"})" -ForegroundColor Yellow
}
Write-Host " > DFS-R Folder Member Enabled.........: $dfsrGroupTopologyMemberSubscriptionEnabledAfter" -ForegroundColor Yellow
Write-Host " > DFS-R Folder Member Options.........: $dfsrGroupTopologyMemberSubscriptionOptionsAfter" -ForegroundColor Yellow
Write-Host " > DFS-R Folder State..................: $dfsrGroupTopologyMemberSubscriptionStateAfter" -ForegroundColor Yellow
Write-Host ""
}
}
}
Write-Host "Press Any Key (TWICE!) To Continue With The NEXT Action..." -ForeGroundColor Magenta
Write-Host ""
Write-Host ""
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment