Public/Get-ADLocalDC.ps1
|
Function Get-ADLocalDC() { <# .SYNOPSIS This function will attempt to return an available domain controller in the same Active Directory site as the computer calling the function. It provides functionality to use either .net calls (default) or the ActiveDirectory module for Powershell cmdlet to validate the availability of the Domain Controller IMPORTANT: This function relies on the function Get-ADComputerSite which is available in this module .PARAMETER UsePsAdCommand Optional. Switch. Default = false. This will use the PowerShell module for ActiveDirectory command "Get-ADDomain" to validate the domain controller availability. This is useful for testing AD WebServices availability. If this parameter is not specified the domain controller will be validated using the .net System.DirectoryServices.DirectoryEntry class. .PARAMETER Verbose Optional. This will print the steps taken to discover the DC in the local site .DESCRIPTION This function uses the .net class System.DirectoryServices.ActiveDirectory.DomainController to discover the domain controllers in the AD site. Each DC is tested in turn until a valid Domain Controller has been discovered. .INPUTS See parameters. .OUTPUTS This function will return a string containing an available domain controller located in the same AD site as the computer calling the function. .EXAMPLE Import-Module ps_Module_ActiveDirectoryTools $sDomainController = Get-ADLocalDC .NOTES MVogwell - October 2022 - Version 1.0 Version history: 1.0 - Initial tested release #> [CmdletBinding()] param ( [Parameter(Mandatory=$false)][switch]$UsePsAdCommand ) # dotsource private functions required for operation $sPathADDomainControllerDirectoryEntry = ($PSScriptRoot).Replace("Public","Private") + "\Get-ADDomainControllerDirectoryEntry.ps1" $sPathADDomainControllersBySite = ($PSScriptRoot).Replace("Public","Private") + "\Get-ADDomainControllersBySite.ps1" Write-Verbose $sPathADDomainControllerDirectoryEntry Write-Verbose $sPathADDomainControllersBySite . $sPathADDomainControllersBySite . $sPathADDomainControllerDirectoryEntry $ErrorActionPreference = "Stop" # This function attempts to discover an available domain controller in the local AD site # The UsePsADCommand $sRtnDcName = "" # Get local AD site name - call function to get this. This could trigger an error $sAdSiteName = Get-ADComputerSite # Search for the domain controllers on the local site $arrDomainControllers = Get-ADDomainControllersBySite -sADSiteName $sAdSiteName # Confirm at least one DC has been returned if ($null -eq $arrDomainControllers) { throw "Failed to discover any domain controllers" } # Test the availability of the domain controllers foreach ($objDc in $arrDomainControllers) { Write-Verbose "`t=== Testing DC: $($objDc.Name)" $objAd = $null try { if ($UsePsAdCommand -eq $true) { $objAd = Get-ADDomain -Server $objDc.Name -ErrorAction "Stop" # If the search was successful if (!($null -eq $objAD)) { $sRtnDcName = $objDc.name Write-Verbose "`t`t+++ Successfully tested $($objDc.Name)" break # escape the AD loop } else { Write-Verbose "`t`t--- DC $($objDc.Name) did not respond to Get-ADDomain" } } else { # Validate the domain controller availabl $sDirectoryEntryPath = "LDAP://" + $objDc.Name + "/RootDSE" # Call a function (in private in this module) to request RootDSE directory entry info from # the specified domain controller - this proves whether the DC is avaialble $objAd = Get-ADDomainControllerDirectoryEntry -sDirectoryEntryPath $sDirectoryEntryPath if (!($null -eq $objAd)) { if ((($objAd | Get-Member -MemberType Properties | Select-Object -ExpandProperty name) -contains "defaultNamingContext") -eq $true) { $sRtnDcName = $objDc.name Write-Verbose "`t`t+++ SUCCESS: DC '$($objDc.Name)' has been validated" break # escape the AD loop } else { Write-Verbose "`t`t--- DC '$($objDc.Name)' did not respond with a valid defaultNamingContext value" } } else { Write-Verbose "`t`t--- DC '$($objDc.Name)' did not response with any valid data" } Remove-Variable sDirectoryEntryPath,objAd -ErrorAction "SilentlyContinue" } } catch { $objAd = $null $sErrMsg = ("Domain Controller '$($objDc.Name)' not available. Error: " + (($Global:Error[0].exception).toString()).replace("`r"," ").replace("`n"," ")) Write-Verbose "`t`t--- $sErrMsg" throw $sErrMsg } } # Check that a DC was discovered - throw error if not found if ([string]::IsNullOrEmpty($sRtnDcName) -eq $true) { throw "Failed to discover an available Domain Controller in the local site" } return $sRtnDcName } |