Private/Set-BestDomainController.ps1
|
function Set-BestDomainController { ################################################################################ ##### ##### ##### Get best DC based on LDAP port availability, PDC role & RODC status ##### ##### ##### ################################################################################ [CmdletBinding()] param( [int]$ThrottleLimit = 20, [int]$TimeoutMs = 1500 ) $CurrentFunction = Get-FunctionName Write-Log -Message "### Start Function $CurrentFunction ###" $StartRunTime = (Get-Date).ToString($Script:DateFormatLog) #################### main code | out- host ##################### $forest = Get-ADForest $rootDomain = $forest.RootDomain $allDCs = foreach ($domain in $forest.Domains) { try { $domainInfo = Get-ADDomain -Server $domain $pdcFQDN = $domainInfo.PDCEmulator Get-ADDomainController -Filter * -Server $domain | ForEach-Object { $fqdn = if ($_.HostName) { $_.HostName } else { "$($_.Name).$($_.Domain)" } [PSCustomObject]@{ Domain = $_.Domain DC_Name = $_.Name FQDN = $fqdn IPv4 = $_.IPv4Address Site = $_.Site IsPDC = ($fqdn -eq $pdcFQDN) IsRootDomain = ($_.Domain -eq $rootDomain) IsRODC = $_.IsReadOnly } } } catch { <#Do this if a terminating exception happens#> } } $total = $allDCs.Count Write-log -message " >> Found $total Domain Controllers." $job = $allDCs | ForEach-Object -Parallel { $dcTarget = if ($_.IPv4) { $_.IPv4 } else { $_.FQDN } $ping = Test-Connection -ComputerName $dcTarget -Count 1 -Quiet -ErrorAction SilentlyContinue $ldapReachable = $false if ($ping) { try { $tcp = New-Object System.Net.Sockets.TcpClient $iar = $tcp.BeginConnect($dcTarget, 389, $null, $null) $wait = $iar.AsyncWaitHandle.WaitOne($using:TimeoutMs, $false) if ($wait -and $tcp.Connected) { $ldapReachable = $true } $tcp.Close() } catch {} } [PSCustomObject]@{ Domain = $_.Domain DC_Name = $_.DC_Name FQDN = $_.FQDN Site = $_.Site Root_Domain = $_.IsRootDomain PDC_Emulator = $_.IsPDC RODC = $_.IsRODC Online = $ping LDAP_389_Open = $ldapReachable } } -ThrottleLimit $ThrottleLimit -AsJob $results = @() while ($job.State -eq "Running") { $results = Receive-Job $job -Keep $done = $results.Count $percent = [math]::Round(($done / $total) * 100, 2) Write-Progress ` -Activity "Checking Domain Controllers" ` -Status "$done of $total tested" ` -PercentComplete $percent Start-Sleep -Milliseconds 200 } $results = Receive-Job $job Remove-Job $job -Force Write-Progress -Activity "Checking Domain Controllers" -Completed $4logfile = $results | Sort-Object Domain, DC_Name | Format-Table -AutoSize | Out-String Write-log -Message " >> Domain Controller Health Overview: $4logfile" $bestdcs = $results | Where-Object LDAP_389_Open | Sort-Object Domain, @{e = { -not $_.PDC_Emulator } }, @{e = { $_.RODC } } | Group-Object Domain | ForEach-Object { $_.Group[0] } $bestdcs = $bestdcs | Select-Object @{N = 'RootDomain'; E = { $_.Root_Domain } }, @{N = 'Domain'; E = { $_.Domain } }, @{N = 'DC'; E = { $_.DC_Name } }, RODC, @{N = 'PDC'; E = { $_.PDC_Emulator } }, Site, Online, @{N = 'Open LDAP Port'; E = { $_.LDAP_389_Open } }, FQDN | Sort-Object RootDomain, FQDN -Descending $logfile = $bestdcs | Format-Table -AutoSize | Out-String Write-log -Message " >> Best Domain Controller per Domain to use: $logfile" $bestdcs | ForEach-Object { $Script:BestDCs[$_.Domain] = $_.FQDN } ######################## main code ############################ $runtime = Get-RunTime -StartRunTime $StartRunTime Write-Log -Message " Run Time: $runtime [h] ###" Write-Log -Message "### End Function $CurrentFunction ###" return $Script:BestDCs } |