Active Directory Replication Analysis Tool

<#
.SYNOPSIS
Active Directory Replication Analysis Tool

.DESCRIPTION
This script analyzes Active Directory replication status, identifies issues,
and provides detailed information about replication topology and health.

.NOTES
File Name      : ADReplicationAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Active Directory module, and appropriate AD permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\ADReplicationAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\AD_Replication_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Active Directory Replication Analysis Tool ===" -ForegroundColor Cyan
    Write-Host "1. Check Replication Status"
    Write-Host "2. Analyze Replication Topology"
    Write-Host "3. Identify Replication Errors"
    Write-Host "4. Check Inter-Site Replication"
    Write-Host "5. Verify Domain Controller Metadata"
    Write-Host "6. Check KCC Connectivity"
    Write-Host "7. Analyze Replication Latency"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Checks the overall replication status.

.OUTPUTS
Array of PSObjects containing replication status details.
#>
function Check-ReplicationStatus {
    Write-Host "`nChecking Replication Status..." -ForegroundColor Yellow
    $results = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $replicationStatus = repadmin /showrepl $dc.HostName
        $lastReplication = ($replicationStatus | Select-String "Last attempt" | Select-Object -First 1) -replace "Last attempt @ ",""
        $results += [PSCustomObject]@{
            DomainController = $dc.HostName
            LastReplication = $lastReplication
            Status = if ($replicationStatus -match "was successful") { "Successful" } else { "Failed" }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes the replication topology.

.OUTPUTS
Array of PSObjects containing replication topology details.
#>
function Analyze-ReplicationTopology {
    Write-Host "`nAnalyzing Replication Topology..." -ForegroundColor Yellow
    $topology = @()
    $sites = Get-ADReplicationSite -Filter *
    foreach ($site in $sites) {
        $siteLinks = Get-ADReplicationSiteLink -Filter {SitesIncluded -eq $site.DistinguishedName}
        $dcs = Get-ADDomainController -Filter {Site -eq $site.Name}
        $topology += [PSCustomObject]@{
            SiteName = $site.Name
            DomainControllers = ($dcs | ForEach-Object { $_.Name }) -join ", "
            ConnectedSites = ($siteLinks | ForEach-Object { ($_.SitesIncluded | Where-Object { $_ -ne $site.DistinguishedName }) -replace "CN=|,.*" }) -join ", "
        }
    }
    $topology | Format-Table -AutoSize
    return $topology
}

<#
.SYNOPSIS
Identifies replication errors.

.OUTPUTS
Array of PSObjects containing replication error details.
#>
function Identify-ReplicationErrors {
    Write-Host "`nIdentifying Replication Errors..." -ForegroundColor Yellow
    $errors = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $replicationStatus = repadmin /showrepl $dc.HostName
        $errorLines = $replicationStatus | Select-String "Error"
        foreach ($line in $errorLines) {
            $errors += [PSCustomObject]@{
                DomainController = $dc.HostName
                Error = $line.Line.Trim()
            }
        }
    }
    if ($errors.Count -eq 0) {
        Write-Host "No replication errors found." -ForegroundColor Green
    } else {
        $errors | Format-Table -AutoSize
    }
    return $errors
}

<#
.SYNOPSIS
Checks inter-site replication.

.OUTPUTS
Array of PSObjects containing inter-site replication details.
#>
function Check-InterSiteReplication {
    Write-Host "`nChecking Inter-Site Replication..." -ForegroundColor Yellow
    $interSiteRepl = @()
    $siteLinks = Get-ADReplicationSiteLink -Filter *
    foreach ($link in $siteLinks) {
        $interSiteRepl += [PSCustomObject]@{
            SiteLinkName = $link.Name
            Sites = ($link.SitesIncluded | ForEach-Object { ($_ -replace "CN=|,.*") }) -join ", "
            ReplicationInterval = $link.ReplicationFrequencyInMinutes
            Cost = $link.Cost
        }
    }
    $interSiteRepl | Format-Table -AutoSize
    return $interSiteRepl
}

<#
.SYNOPSIS
Verifies domain controller metadata.

.OUTPUTS
Array of PSObjects containing DC metadata details.
#>
function Verify-DCMetadata {
    Write-Host "`nVerifying Domain Controller Metadata..." -ForegroundColor Yellow
    $metadata = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $dcMetadata = Get-ADReplicationPartnerMetadata -Target $dc.HostName
        $metadata += [PSCustomObject]@{
            DomainController = $dc.HostName
            LastReplicationAttempt = $dcMetadata.LastReplicationAttempt
            LastReplicationResult = $dcMetadata.LastReplicationResult
            LastReplicationSuccess = $dcMetadata.LastReplicationSuccess
        }
    }
    $metadata | Format-Table -AutoSize
    return $metadata
}

<#
.SYNOPSIS
Checks KCC connectivity.

.OUTPUTS
Array of PSObjects containing KCC connectivity details.
#>
function Check-KCCConnectivity {
    Write-Host "`nChecking KCC Connectivity..." -ForegroundColor Yellow
    $kccConnectivity = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $kccStatus = repadmin /showkcc $dc.HostName
        $kccConnectivity += [PSCustomObject]@{
            DomainController = $dc.HostName
            Status = if ($kccStatus -match "completed successfully") { "Successful" } else { "Failed" }
            Details = ($kccStatus | Select-String "Intra" -Context 0,1).Context.PostContext
        }
    }
    $kccConnectivity | Format-Table -AutoSize
    return $kccConnectivity
}

<#
.SYNOPSIS
Analyzes replication latency.

.OUTPUTS
Array of PSObjects containing replication latency details.
#>
function Analyze-ReplicationLatency {
    Write-Host "`nAnalyzing Replication Latency..." -ForegroundColor Yellow
    $latency = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $replPartners = Get-ADReplicationPartnerMetadata -Target $dc.HostName
        foreach ($partner in $replPartners) {
            $latency += [PSCustomObject]@{
                SourceDC = $dc.HostName
                PartnerDC = $partner.Partner
                LastReplicationAttempt = $partner.LastReplicationAttempt
                LastReplicationSuccess = $partner.LastReplicationSuccess
                LatencyMinutes = if ($partner.LastReplicationSuccess) {
                    [math]::Round(($partner.LastReplicationAttempt - $partner.LastReplicationSuccess).TotalMinutes, 2)
                } else { "N/A" }
            }
        }
    }
    $latency | Format-Table -AutoSize
    return $latency
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AD Replication Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Active Directory Replication Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Replication Status</h2>
    $($AllResults.ReplicationStatus | ConvertTo-Html -Fragment)

    <h2>Replication Topology</h2>
    $($AllResults.ReplicationTopology | ConvertTo-Html -Fragment)

    <h2>Replication Errors</h2>
    $($AllResults.ReplicationErrors | ConvertTo-Html -Fragment)

    <h2>Inter-Site Replication</h2>
    $($AllResults.InterSiteReplication | ConvertTo-Html -Fragment)

    <h2>Domain Controller Metadata</h2>
    $($AllResults.DCMetadata | ConvertTo-Html -Fragment)

    <h2>KCC Connectivity</h2>
    $($AllResults.KCCConnectivity | ConvertTo-Html -Fragment)

    <h2>Replication Latency</h2>
    $($AllResults.ReplicationLatency | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.ReplicationStatus = Check-ReplicationStatus }
        "2" { $allResults.ReplicationTopology = Analyze-ReplicationTopology }
        "3" { $allResults.ReplicationErrors = Identify-ReplicationErrors }
        "4" { $allResults.InterSiteReplication = Check-InterSiteReplication }
        "5" { $allResults.DCMetadata = Verify-DCMetadata }
        "6" { $allResults.KCCConnectivity = Check-KCCConnectivity }
        "7" { $allResults.ReplicationLatency = Analyze-ReplicationLatency }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Active Directory Replication Analysis Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of AD replication:
    • Overall replication status check
    • Replication topology analysis
    • Identification of replication errors
    • Inter-site replication check
    • Domain controller metadata verification
    • KCC (Knowledge Consistency Checker) connectivity check
    • Replication latency analysis
  3. Comprehensive error handling for each analysis function.
  4. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of replication status across all domain controllers
  • Visualization of replication topology, including sites and links
  • Identification and reporting of replication errors
  • Analysis of inter-site replication configuration
  • Verification of domain controller metadata for replication health
  • Check of KCC connectivity to ensure proper replication partner selection
  • Analysis of replication latency to identify slow replication issues
  • Comprehensive HTML report generation

This tool is particularly useful for:

  • Active Directory administrators managing complex multi-site environments
  • IT professionals troubleshooting AD replication issues
  • System administrators performing regular health checks on AD infrastructure

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query AD replication in your domain
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of the AD replication status and health in an Active Directory environment, making it easier to identify issues, bottlenecks, or misconfigurations related to replication. It can significantly streamline the process of troubleshooting and maintaining AD replication in large or complex environments.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *