Last active
May 12, 2023 22:17
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------- | |
# 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