This function is about locating a domain controller that is up and running by validating its response on port 389 and return a random working, all working or even best responsive domain controller. This function supports exchange and active directory PowerShell commands from any pc and support for workflows. Additional parameters can be used to filter down specific roles like Global catalog or Active Directory Web Services. You can query any domain from any pc as long as there is tcp connectivity between the computers and you have a account that can authenticate against the domain controllers. If you do not select a active directory site the function will try to resolve the site of the host pc running the function. If no site info can be resolved all the domain controllers of the domain will be tested. The script is written to use .NET framework so no additional modules are needed. Due to this the script is 100% compatible to run in PowerShell workflows, PowerShell Parallel workflows, parallel run spaces or C# run spaces utilizing PowerShell. Below is a recap of the full functionality of the script and new features.    

For more information look at my site: Http://www.tech-savvy.nl

Function name : Get-Dc
        Authors       : Martijn (scriptkiddie) van Geffen
        Version       : 1.3


      Version Changes:
        10-10-2016 V0.1: Initial Script
        06-12-2016 V0.2: updated script with credential support and doubble ping
        12-12-2016 V1.0: Fixed a issue with the credentials when querying from a domain joined PC
        17-01-2017 v1.1: Updated "Site" param to "ADsite" and try to resolve default AD site if the param is not specified
        27-01-2017 v1.2: Added an additional loop for cross forest DC lookup. If the script won`t find a DC in the site it will retry all sites  
        17-10-2017 v1.3: Added support for specific AD role Global catalog
                                   Added support for specific AD role Active directory web services
                                   Added support to return list of all working DC`s
                                   Added alias gdc - Powershell V5 only
                                   Update code error handling 
                                   Added verbose & debug output

 

PowerShell
Edit|Remove
function Get-Dc 
{ 
    <# 
    .SYNOPSIS 
        Find a DC in a domain that is up and running by probing the DC port 389 
        Find a DC with GC role in a domain that is up and running by probing the DC port 3268 
        Find a DC with ADWS role in a domain that is up and running by probing the DC port 9389 
        List a single , best responsive or all servers found 
    .DESCRIPTION 
        Find all DC`s within your query range and probe if it responds to the AD port and return a working DC, all working DC or  
        best available DC. 
        If the site parameter is not specified it will use the computers AD site if it resolves. Otherwise it will use all AD Sites. 
        A subset of DC`s with a specific role can be specified using switches -isgc and/or -isadws. 
        Return a random server that is working, return all working servers or return the best responsive server based on ping response.  
    .EXAMPLE 
        Get-Dc 
 
        Get all DC`s from the current computers site. Return a random working DC 
    .EXAMPLE 
        Get-Dc -listall 
 
        Get all DC`s from the current computers site. Return list of all working Domain controllers 
    .EXAMPLE 
        Get-Dc -ADsite "*" 
 
        Get all DC`s from the logged on Domain. Return a random working DC 
    .EXAMPLE 
        Get-Dc -ADSite "Newyork" 
     
        Get all DC`s from the logged on Domain in the AD site Newyork. Return a random working DC 
    .EXAMPLE 
        Get-Dc -ADSite "Newyork" -isgc -isadws 
     
        Get all DC`s from the logged on Domain in the AD site Newyork. filter out DC`s running GC and ADWS services. 
        Return a random working DC 
    .EXAMPLE 
        Get-Dc -Domain "contoso.com" -ADSite "Newyork" -Bestresponsetime 
     
        Get all DC`s from the domain contoso.com in the AD site Newyork and probe for best response time. Return the fastest responding DC 
    .EXAMPLE 
        Get-Dc -Domain "contoso.com" -ADSite "Newyork" -Bestresponsetime -cred (get-credential) 
     
        Get all DC`s from the domain contoso.com in the AD site Newyork and probe for best response time. Return the fastest responding DC 
        Use a interactive credential prompt to provide credentials 
 
    .NOTES 
        ----------------------------------------------------------------------------------------------------------------------------------- 
        Function name : Get-Dc 
        Authors       : Martijn (scriptkiddie) van Geffen 
        Version       : 1.3 
        dependancies  : None 
        ----------------------------------------------------------------------------------------------------------------------------------- 
        ----------------------------------------------------------------------------------------------------------------------------------- 
        Version Changes: 
        Date: (dd-MM-YYYY)    Version:     Changed By:           Info: 
        10-10-2016            V0.1         Martijn van Geffen    Initial Script. 
        06-12-2016            V0.2         Martijn van Geffen    Updated script with credential support and doubble ping. 
        12-12-2016            V1.0         Martijn van Geffen    Fixed a issue with the credentials when querying from a domain joined PC. 
        17-01-2017            v1.1         Martijn van Geffen    Updated "Site" param to "ADsite" and try to resolve default AD site if the 
                                                                 param is not specified. 
        27-01-2017            v1.2         Martijn van Geffen    Added an aditional loop for cross forest DC lookup. If script won`t find a 
                                                                 DC in the site it will retry all sites. 
        17-10-2017            v1.3         Martijn van Geffen    Added support for specific AD role Global catalog 
                                                                 Added support for specific AD role Active directory web services 
                                                                 Added support to return list of all working DC`s  
                                                                 Added alias gdc 
                                                                 Update code error handling   
                                                                 Added verbose & debug output 
        ----------------------------------------------------------------------------------------------------------------------------------- 
    .OUTPUTS 
        [system.Array]         
    .ROLE 
        None 
    .FUNCTIONALITY 
        Find a DC in a domain that is up and running by probing the DC port 389 
    #> 
 
    [CmdletBinding( 
                        DefaultParameterSetName='return_one', 
                        HelpUri='https://gallery.technet.microsoft.com/scriptcenter/Find-a-working-domain-fe731b4f' 
                   )] 
    [Alias("gdc")] 
    [OutputType([System.Array])] 
 
    param( 
 
        [Parameter(Mandatory=$false)] 
        [ValidateNotNullOrEmpty()] 
        [string]$Domain = ([system.directoryservices.activedirectory.domain]::GetCurrentDomain()).name, 
     
        [Parameter(Mandatory=$false)] 
        [ValidateNotNullOrEmpty()] 
        [string]$ADSite = "getsite", 
 
        [Parameter( 
                        Mandatory=$false, 
                        ParameterSetName='return_one' 
                   )] 
        [switch]$Bestresponsetime, 
 
        [Parameter(Mandatory=$false)] 
        [switch]$isgc, 
 
        [Parameter(Mandatory=$false)] 
        [switch]$isadws, 
 
        [Parameter( 
                        Mandatory=$false, 
                        ParameterSetName='return_all' 
                   )] 
        [switch]$listall, 
 
        [Parameter(Mandatory=$false)] 
        [ValidateNotNullOrEmpty()] 
        [System.Management.Automation.PsCredential]$Cred 
 
    ) 
 
    #region resolve site and domain 
    if ($ADsite -eq "getsite") 
    { 
        try 
        { 
            $ADsite = ([System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite()).name 
            Write-Verbose -Message "Found computer to be in AD site: $ADsite" 
        }catch 
        { 
            $ADsite = "*" 
            Write-Verbose -Message "Could not resolve AD site setting site to *" 
        } 
    } 
 
    if ( $cred ) 
    { 
        $username = $Cred.username 
        $password = $Cred.GetNetworkCredential().password 
        $ADcontext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain,$username,$password) 
    }else 
    { 
        $ADcontext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain) 
    } 
    #endregion resolve site and domain 
 
    #region resolve DC in site 
    $AllDCs = ([system.directoryservices.activedirectory.domain]::GetDomain($ADcontext).domainControllers) 
 
    Write-debug -Message "All domaincontrollers according to AD: $($allDCs)" 
 
    $AllDCinsite = $AllDCs | Where-Object -FilterScript {$_.sitename -like $ADsite } 
    [array]$AllDCinsite = $AllDCinsite.name 
     
    Write-Verbose -Message "All domaincontrollers according to site filter: $($AllDCinsite)" 
 
    If ($AllDCinsite.count -eq 0) 
    { 
        Write-debug -Message "Did not find any DC , retrying with full site scope might be a non local domain" 
        $ADsite = "*" 
        $AllDCinsite = $AllDCs | Where-Object -FilterScript {$_.sitename -like $ADsite } 
        [array]$AllDCinsite = $AllDCinsite.name 
        Write-Verbose -Message "All domaincontrollers after resetting site scope to all sites: $($AllDCinsite)" 
    } 
 
    $AllusableDC = @() 
    #endregion resolve DC in site 
 
    #region test if ADDC is availble for AD querys 
    foreach ($DC in $AllDCinsite) 
    {  
        #validate if server is usable for AD query`s 
         
        try  
        {             
            $socket = New-Object Net.sockets.tcpclient 
            $socket.Connect($DC"389") 
            if ( $socket.Connected ) 
            { 
                $AllusableDC +$DC            
            } 
             
# END OF CODE SNIPPET DOWNLOAD THE SCRIPT FOR THE FULL CODE 
 
# END OF CODE SNIPPET DOWNLOAD THE SCRIPT FOR THE FULL CODE 
 
# END OF CODE SNIPPET DOWNLOAD THE SCRIPT FOR THE FULL CODE