NTS.Tools.MSADDS.psm1

function Install-NLASvcFixForDCs {
    <#
        .Description
        checks if dns is specified as dependy for service nlasvc and if its not the case it will add it.
 
        .Example
        # this will service dns as dependency for the service nlasvc
        Install-NLASvcFixForDCs
 
        .NOTES
         
    #>


    try {
        $RegKey = "HKLM:\SYSTEM\CurrentControlSet\Services\NlaSvc"
        $RegKeyValue = "DependOnService"
        $ServiceName = "DNS"

        Write-Output "$($env:COMPUTERNAME): adding service $($ServiceName) as dependency for service NlaSvc"
        $NLASvcDependencies = (Get-ItemProperty -Path $RegKey -Name $RegKeyValue).$RegKeyValue
        if ($NLASvcDependencies -notcontains $ServiceName) {
            $FixedNLASvcDependencies = $NLASvcDependencies + $ServiceName
            Set-ItemProperty -Path $RegKey -Name $RegKeyValue -Value $FixedNLASvcDependencies
            Write-Output "$($env:COMPUTERNAME): NlaSvc fix applied"
        }
        else {
            Write-Output "$($env:COMPUTERNAME): NlaSvc fix already applied"
        }
    }
    catch {
        throw $PSItem.Exception.Message
    }
}

function New-EASEOUStructure {
    <#
        .Description
        this will create the esae structure with OUs, User, Groups and Group Managed Service Accounts
 
        .Example
        # creates the ease structure on the local domain controller
        New-EASEOUStructure
 
        .NOTES
        must be executed on a domain controller
         
    #>


    if ((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType -ne 2) {
        throw "$($env:COMPUTERNAME): this is not a domain controller, can only be used on domain controllers"
    }
    
    Import-Module "Activedirectory"
    $Domain = Get-ADDomain

    Write-Output "$($env:COMPUTERNAME): apply esae structure on $($Domain.Forest)"
    
    #region ous
    try {
        Write-Output "$($env:COMPUTERNAME): creating ous"
        $TopLevelOU = 'ESAE'
        New-ADOrganizationalUnit -Name $TopLevelOU -Path $Domain.DistinguishedName
        
        # ESAE
        $ESAEPath = "OU=$TopLevelOU,$($Domain.DistinguishedName)"
        $ESAEOUs = 'Groups', 'PAW', 'Tier 0', 'Tier 1', 'Tier 2' 
        $ESAEOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $ESAEPath
        }
            
        # ESAE\PAW
        $PAWPath = "OU=PAW,$ESAEPath"
        $PAWOUs = 'Accounts', 'Devices', 'Groups' 
        $PAWOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $PAWPath 
        }
            
        # ESAE\Tier0
        $Tier0Path = "OU=Tier 0,$ESAEPath"
        $Tier0OUs = 'AD', 'PKI', 'SQL', 'ADFS', 'ADSync'
        $Tier0OUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0Path 
        }
            
        # ESAE\Tier1
        $Tier1Path = "OU=Tier 1,$ESAEPath"
        $Tier1OUs = 'Exchange', 'ConfigMgr', 'SQL'
        $Tier1OUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier1Path
        }
            
        # ESAE\Tier2
        $Tier2Path = "OU=Tier 2,$ESAEPath"
        $Tier2OUs = 'Accounts', 'Devices', 'Groups'
        $Tier2OUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier2Path
        }
            
        # ESAE\Tier0\AD
        $Tier0ADPath = "OU=AD,$Tier0Path"
        $Tier0ADOUs = 'Accounts', 'Groups' 
        $Tier0ADOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0ADPath
        }
            
        # ESAE\Tier0\PKI
        $Tier0PKIPath = "OU=PKI,$Tier0Path"
        $Tier0PKIOUs = 'Accounts', 'Groups', 'Servers'
        $Tier0PKIOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0PKIPath 
        }
        
        # ESAE\Tier0\SQL
        $Tier0SQLPath = "OU=SQL,$Tier0Path"
        $Tier0SQLOUs = 'Accounts', 'Groups', 'Servers'
        $Tier0SQLOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0SQLPath 
        }
    
        # ESAE\Tier0\ADFS
        $Tier0ADFSPath = "OU=ADFS,$Tier0Path"
        $Tier0ADFSOUs = 'Accounts', 'Groups', 'Servers'
        $Tier0ADFSOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0ADFSPath 
        }
    
        # ESAE\Tier0\ADSync
        $Tier0ADSyncPath = "OU=ADSync,$Tier0Path"
        $Tier0ADSyncOUs = 'Accounts', 'Groups', 'Servers'
        $Tier0ADSyncOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier0ADSyncPath 
        }
    
        # ESAE\Tier1\Exchange
        $Tier1ExchangePath = "OU=Exchange,$Tier1Path"
        $Tier1ExchangeOUs = 'Accounts', 'Groups', 'Servers'
        $Tier1ExchangeOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier1ExchangePath 
        }
            
        # ESAE\Tier1\ConfigMgr
        $Tier1ConfigMgrPath = "OU=ConfigMgr,$Tier1Path"
        $Tier1ConfigMgrOUs = 'Accounts', 'Groups', 'Servers'
        $Tier1ConfigMgrOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier1ConfigMgrPath 
        }
            
        # ESAE\Tier1\SQL
        $Tier1SQLPath = "OU=SQL,$Tier1Path"
        $Tier1SQLOUs = 'Accounts', 'Groups', 'Servers'
        $Tier1SQLOUs | ForEach-Object { 
            New-ADOrganizationalUnit -Name $PSItem -Path $Tier1SQLPath
        }
    }
    catch {
        throw "error creating ous: $($PSItem.Exception.Message)"
    }
    #endregion

    #region groups
    try {
        Write-Output "$($env:COMPUTERNAME): creating groups"
        # PAW
        $GroupNames = 'T0-Allowed', 'T1-Allowed', 'T2-Allowed', 'T0-Denied', 'T1-Denied', 'T2-Denied'
        $GroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$ESAEPath"
        }
        $PAWGroupNames = 'PAW-Devices', 'PAW-Maintenance', 'PAW-Users'
        $PAWGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$PAWPath"
        }

        # T0
        $Tier0ADGroupNames = 'T0-CloudAdmins', 'T0-DomAdmins', 'T0-EntAdmins', 'T0-RODCAdmins', 'T0-SchAdmins'
        $Tier0ADGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier0ADPath"
        }
        $Tier0PKIGroupNames = 'T0-PKIAdmins', 'T0-PKISCAgents'
        $Tier0PKIGroupNames | ForEach-Object {
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier0PKIPath"
        }
        $Tier0SQLGroupNames = 'T0-SQLAdmins', 'T0-SQLServers'
        $Tier0SQLGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier0SQLPath"
        }
        $Tier0ADFSGroupNames = 'T0-ADFSAdmins', 'T0-ADFSServers', 'T0-ADFSSQLServers'
        $Tier0ADFSGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier0ADFSPath"
        }
        $Tier0ADSyncGroupNames = 'T0-ADSyncAdmins', 'T0-ADSyncServers', 'T0-ADSyncSQLServers'
        $Tier0ADSyncGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier0ADSyncPath"
        }

        # T1
        $Tier1ExchangeGroupNames = 'T1-ExAdmins', 'T1-ExAllowed', 'T1-ExMaintenance', 'T1-ExMBXAdmins', 'T1-ExOrgAdmins'
        $Tier1ExchangeGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier1ExchangePath"
        }
        $Tier1CMGroupNames = 'T1-CMAdmins', 'T1-CMServers', 'T1-CMSQLServers'
        $Tier1CMGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier1ConfigMgrPath"
        }
        $Tier1SQLGroupNames = 'T1-SQLAdmins', 'T1-SQLServers'
        $Tier1SQLGroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier1SQLPath"
        }

        # T2
        $Tier2GroupNames = 'T2-HelpDesk'
        $Tier2GroupNames | ForEach-Object { 
            New-ADGroup -Name $PSItem -SamAccountName $PSItem -GroupCategory Security -GroupScope Universal -DisplayName $PSItem -Path "OU=Groups,$Tier2Path"
        }
    }
    catch {
        throw "error creating groups: $($PSItem.Exception.Message)"
    }
    #endregion

    #region users
    try {
        Write-Output "$($env:COMPUTERNAME): creating users"
        $Password = ConvertTo-SecureString -String 'C0mplex' -AsPlainText -Force

        # PAW
        $PAWUserNames = 'PAWMan1'
        $PAWUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$PAWPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
    
        # T0
        $Tier0ADUserNames = 'T0-DomAdmin1', 'T0-EntAdmin1'
        $Tier0ADUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier0ADPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier0PKIUserNames = 'T0-PKIAdmin1', 'T0-PKISCA1'
        $Tier0PKIUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier0PKIPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier0SQLUserNames = 'T0-SQLAdmin1', 'T0-SQLAdmin2'
        $Tier0SQLUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier0SQLPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier0ADFSUserNames = 'T0-ADFSAdmin1', 'T0-ADFSAdmin2'
        $Tier0ADFSUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier0ADFSPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier0ADSyncUserNames = 'T0-ADSyncAdmin1', 'T0-ADSyncAdmin2'
        $Tier0ADSyncUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier0ADSyncPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
    
        # T1
        $Tier1ExchangeUserNames = 'T1-ExAdmin1', 'T1-ExAdmin2'
        $Tier1ExchangeUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier1ExchangePath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier1CMUserNames = 'T1-CMAdmin1', 'T1-CMAdmin2', 'T1-CMSQLRPT'
        $Tier1CMUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier1ConfigMgrPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
        $Tier1SQLUserNames = 'T1-SQLAdmin1', 'T1-SQLAdmin2'
        $Tier1SQLUserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier1SQLPath" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
    
        # T2
        $Tier2UserNames = 'T2-HelpDesk1', 'T2-HelpDesk2'
        $Tier2UserNames | ForEach-Object { 
            New-ADUser -Name $PSItem -Path "OU=Accounts,$Tier2Path" -SamAccountName $PSItem -UserPrincipalName "$PSItem@$($Domain.Forest)" -GivenName $PSItem -DisplayName $PSItem -AccountPassword $Password -Enabled $true -PasswordNeverExpires $true
        }
    }
    catch {
        throw "error creating users: $($PSItem.Exception.Message)"
    }
    #endregion

    #region gmsa
    try {
        Write-Output "$($env:COMPUTERNAME): creating gmsa"
        Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10) | Out-Null
        # T0
        New-ADServiceAccount -Name "T0-SQLSvc" -DNSHostName "T0-SQLSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-SQLServers"
        New-ADServiceAccount -Name "T0-SQLAgt" -DNSHostName "T0-SQLAgt.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-SQLServers"
        # T0\ADFS
        New-ADServiceAccount -Name "T0-ADFSSvc" -DNSHostName "T0-ADFSSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADFSServers"
        New-ADServiceAccount -Name "T0-ADFSSQLSvc" -DNSHostName "T0-ADFSSQLSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADFSSQLServers"
        New-ADServiceAccount -Name "T0-ADFSSQLAgt" -DNSHostName "T0-ADFSSQLAgt.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADFSSQLServers"
        # T0\ADSync
        New-ADServiceAccount -Name "T0-ADSyncSvc" -DNSHostName "T0-ADSyncSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADSyncServers"
        New-ADServiceAccount -Name "T0-ADSyncSQLSvc" -DNSHostName "T0-ADSyncSQLSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADSyncSQLServers"
        New-ADServiceAccount -Name "T0-ADSyncSQLAgt" -DNSHostName "T0-ADSyncSQLAgt.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T0-ADSyncSQLServers"
    
        # T1
        New-ADServiceAccount -Name "T1-SQLSvc" -DNSHostName "T1-SQLSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T1-SQLServers"
        New-ADServiceAccount -Name "T1-SQLAgt" -DNSHostName "T1-SQLAgt.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T1-SQLServers"
        # T1\ConfigMgr
        New-ADServiceAccount -Name "T1-CMSQLSvc" -DNSHostName "T1-CMSQLSvc.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T1-CMSQLServers"
        New-ADServiceAccount -Name "T1-CMSQLAgt" -DNSHostName "T1-CMSQLAgt.$($Domain.Forest)" -PrincipalsAllowedToRetrieveManagedPassword "T1-CMSQLServers"
    }
    catch {
        throw "error creating gmsa: $($PSItem.Exception.Message)"
    }
    #endregion

    #region group membership
    try {
        Write-Output "$($env:COMPUTERNAME): creating group membership"
        # Tier Groups
        $Tier0AllowedGroups = 'T0-CloudAdmins', 'T0-DomAdmins', 'T0-EntAdmins', 'T0-RODCAdmins', 'T0-SchAdmins', 'T0-PKIAdmins', 'T0-PKISCAgents', 'T0-SQLAdmins', 'T0-ADFSAdmins', 'T0-ADSyncAdmins'
        $Tier1AllowedGroups = 'T1-CMAdmins', 'T1-ExAdmins', 'T1-ExAllowed', 'T1-ExMaintenance', 'T1-ExMBXAdmins', 'T1-ExOrgAdmins', 'T1-SQLAdmins'
        $Tier2AllowedGroups = 'T2-HelpDesk'
        Add-ADGroupMember -Identity 'T0-Allowed' -Members $Tier0AllowedGroups
        Add-ADGroupMember -Identity 'T0-Denied' -Members ($Tier1AllowedGroups + $Tier2AllowedGroups)
        Add-ADGroupMember -Identity 'T1-Allowed' -Members $Tier1AllowedGroups
        Add-ADGroupMember -Identity 'T1-Denied' -Members ($Tier0AllowedGroups + $Tier2AllowedGroups)
        Add-ADGroupMember -Identity 'T2-Allowed' -Members $Tier2AllowedGroups
        Add-ADGroupMember -Identity 'T2-Denied' -Members ($Tier0AllowedGroups + $Tier1AllowedGroups)

        # PAW
        Add-ADGroupMember -Identity 'PAW-Maintenance' -Members 'PAWMan1'

        # T0
        Add-ADGroupMember -Identity 'Domain Admins' -Members 'T0-DomAdmin1'
        Add-ADGroupMember -Identity 'Enterprise Admins' -Members 'T0-EntAdmin1'
        Add-ADGroupMember -Identity 'T0-PKIAdmins' -Members 'T0-PKIAdmin1'
        Add-ADGroupMember -Identity 'T0-PKISCAgents' -Members 'T0-PKISCA1'
        Add-ADGroupMember -Identity 'T0-SQLAdmins' -Members 'T0-SQLAdmin1', 'T0-SQLAdmin2'

        # T1
        Add-ADGroupMember -Identity 'T1-ExAdmins' -Members 'T1-ExAdmin1', 'T1-ExAdmin2'
        Add-ADGroupMember -Identity 'T1-CMAdmins' -Members 'T1-CMAdmin1', 'T1-CMAdmin2'
        Add-ADGroupMember -Identity 'T1-SQLAdmins' -Members 'T1-SQLAdmin1', 'T1-SQLAdmin2'

        # T2
        Add-ADGroupMember -Identity 'T2-HelpDesk' -Members 'T2-HelpDesk1', 'T2-HelpDesk2'
    }
    catch {
        throw "error creating group memberships: $($PSItem.Exception.Message)"
    }
    #endregion
}

function Repair-DFSRReplication {
    <#
        .Description
        this will forcefully repair dfsr replication on the domain, use with care
 
        .Example
        # this will forcefully repair dfsr replication on the domain
        Repair-DFSRReplication
 
        .NOTES
        must be executed on a domain controller
         
    #>


    $Domain = (Get-ADDomain -Current LoggedOnUser).DistinguishedName
    $PDC = (Get-ADDomain).PDCEmulator
    $DCs = Get-ADObject -Filter { (objectclass -eq "computer") } -SearchBase "OU=Domain Controllers,$Domain" -Properties Name | Sort-Object Name
    
    $DCs | ForEach-Object {
        Invoke-Command -ComputerName $PSItem.Name -ScriptBlock {
            try {
                $Domain = (Get-ADDomain -Current LoggedOnUser).DistinguishedName
                $PDC = (Get-ADDomain).PDCEmulator
                $sysvolADObject = Get-ADObject -Filter { (objectclass -eq "msDFSR-Subscription") } `
                    -SearchBase "CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=$($env:COMPUTERNAME),OU=Domain Controllers,$Domain"`
                    -Properties "msDFSR-Options", "msDFSR-Enabled"
        
                Write-Output "$($env:COMPUTERNAME): Restarting NIC to correct Network Profile"
                $NetAdapter = Get-NetAdapter 
                $NetAdapter[0] | Restart-NetAdapter -Confirm:$false
    
                Write-Output "$($env:COMPUTERNAME): Installing DFSR Management Tools"
                Install-WindowsFeature -Name RSAT-DFS-Mgmt-Con | Out-Null
                if ($($PDC).Contains($env:COMPUTERNAME)) {
                    Write-Output "$($env:COMPUTERNAME): Setting msDFSR-Options to 1"
                    Set-ADObject -Identity $sysvolADObject.DistinguishedName -Replace @{"msDFSR-Options" = 1 }
                }
                Write-Output "$($env:COMPUTERNAME): Setting msDFSR-Enabled to false"
                Set-ADObject -Identity $sysvolADObject.DistinguishedName -Replace @{"msDFSR-Enabled" = $false }
            }
            catch {
                throw $PSItem.Exception.Message
            }
        }
    }
    
    Write-Output "$($env:COMPUTERNAME): Forcing AD Replication"
    repadmin /syncall /P /e
    Start-Sleep(10)

    Invoke-Command -ComputerName $PDC -ScriptBlock {
        try {
            $Domain = (Get-ADDomain -Current LoggedOnUser).DistinguishedName
            $sysvolADObject = Get-ADObject -Filter { (objectclass -eq "msDFSR-Subscription") } `
                -SearchBase "CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=$($env:COMPUTERNAME),OU=Domain Controllers,$Domain"`
                -Properties "msDFSR-Options", "msDFSR-Enabled"
            Write-Output "$($env:COMPUTERNAME): Restarting DFSR Service"
            Restart-Service DFSR 
            Start-Sleep(20)
            Write-Output "$($env:COMPUTERNAME): Setting msDFSR-Enabled to true"
            Set-ADObject -Identity $sysvolADObject.DistinguishedName -Replace @{"msDFSR-Enabled" = $true }
            Write-Output "$($env:COMPUTERNAME): Forcing AD Replication"
            repadmin /syncall /P /e
            Start-Sleep(10)
            Write-Output "$($env:COMPUTERNAME): Executing DFSRDIAG"
            dfsrdiag pollad
        }
        catch {
            $PSItem.Exception.Message
        }
    }
    
    $DCs | ForEach-Object {
        Invoke-Command -ComputerName $PSItem.Name -ScriptBlock {
            try {
                $Domain = (Get-ADDomain -Current LoggedOnUser).DistinguishedName
                $PDC = (Get-ADDomain).PDCEmulator
                $sysvolADObject = Get-ADObject -Filter { (objectclass -eq "msDFSR-Subscription") } `
                    -SearchBase "CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=$($env:COMPUTERNAME),OU=Domain Controllers,$Domain"`
                    -Properties "msDFSR-Options", "msDFSR-Enabled"
                if (!$($PDC).Contains($($env:COMPUTERNAME))) {
                    Write-Output "$($env:COMPUTERNAME): Restarting DFSR Service"
                    Restart-Service DFSR 
                    Start-Sleep(20)
                    Write-Output "$($env:COMPUTERNAME): Setting msDFSR-Enabled to true"
                    Set-ADObject -Identity $sysvolADObject.DistinguishedName -Replace @{"msDFSR-Enabled" = $true }
                    Write-Output "$($env:COMPUTERNAME): Executing DFSRDIAG"
                    dfsrdiag pollad  
                }
            }
            catch {
                throw $PSItem.Exception.Message
            }
        }
    }
}

function Compare-DFSRObject {
    [CmdletBinding()]

    $Domain = Get-ADDomain -Current LoggedOnUser
    $PDC = (Get-ADDomain).PDCEmulator
    $DCs = Get-ADObject -Filter { (objectclass -eq "computer") } -SearchBase "OU=Domain Controllers,$($Domain.DistinguishedName)" -Properties Name,DNSHostName | Where-Object -Property Name -NE "AzureADKerberos" | Sort-Object Name

    $Polices_CompareObject = @{}
    $Scripts_CompareObject = @{}

    # Get Files
    Write-Output "Getting data for comparison"
    $DCs | ForEach-Object {
        # C:\Windows\SYSVOL\sysvol\AZURE-HYBRID.DE\
        $PoliciesPath = "\\$($PSItem.DNSHostName)\C$\Windows\SYSVOL\domain\Policies"
        $ScriptsPath = "\\$($PSItem.DNSHostName)\C$\Windows\SYSVOL\domain\scripts"

        $Polices_CompareObject.add("$($PSItem.DNSHostName)",$(Get-ChildItem -Path $PoliciesPath).count)
        $Scripts_CompareObject.add("$($PSItem.DNSHostName)",$(Get-ChildItem -Path $ScriptsPath).count)
    }

    # Compare files count
    Write-Output "Comparing data"
    $Polices_CompareObject.Keys | ForEach-Object {
        if($Polices_CompareObject."$($PDC)" -ne $Polices_CompareObject.$($PSItem)) {
            Write-Output "--------------------------------------------------------"
            Write-Warning "$($PSItem) is not in sync with $($PDC) at folder Policies"
            Write-Warning "$($PDC): $($Polices_CompareObject."$($PDC.Trim())") <---> $($PSItem): $($Polices_CompareObject.$($PSItem))"            
        }
        else {
            Write-Output "$($PSItem) is in sync with $($PDC) at folder Policies"
        }
    }
    $Scripts_CompareObject.Keys | ForEach-Object {
        if($Scripts_CompareObject."$($PDC)" -ne $Scripts_CompareObject.$($PSItem)) {
            Write-Output "--------------------------------------------------------"
            Write-Warning "$($PSItem) is not in sync with $($PDC) at folder Scripts"
            Write-Warning "$($PDC): $($Scripts_CompareObject."$($PDC.Trim())") <---> $($PSItem): $($Scripts_CompareObject.$($PSItem))"            
        }
        else {
            Write-Output "$($PSItem) is in sync with $($PDC) at folder Scripts"
        }
    }
}