Posts RSS Comments RSS 253 Posts and 411 Comments till now

Check Active Directory Latency

The other day I had a need to see how long it took for an object to be replicated to all the Domain Controllers in my Environment.

Here is the script I came up with. It does the following:
– Finds all Domain Controllers in the Domain (using .NET)
– Creates a contact object in a specified OU (Default is users container for the Domain)
– Gets the start Time
– Loops and Checks each DC for the object.
– Once all DCs have the object it gets End Time
– Outputs the results

Some extra features
– re-writes screen using $host.UI.RawUI.CursorPosition. No scrolling text 🙂
– Outputs a custom object with Name and Time to Replicate (-table)

Parameters/Switches
-target: DC to create object on. (Default: it will find one for you)
-fqdn: Used to Find Domain Controllers (Default: Use current Domain)
-ou: DN of the path to create contact objects (Default Users Container)
-remove: If $true it removes the temp object (default is $true)
-table: switch that will return a table with the DC and Time it took to replicate (as output)

Here is the code:

Param($target = (([ADSI]"LDAP://rootDSE").dnshostname),
      $fqdn = (([ADSI]"").distinguishedname -replace "DC=","" -replace ",","."),
      $ou = ("cn=users," + ([ADSI]"").distinguishedname),
      $remove = $true,
      [switch]$table
      )

$context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain",$fqdn)
$dclist = [System.DirectoryServices.ActiveDirectory.DomainController]::findall($context)
if($table)
{
    $DCTable = @()
    $myobj = "" | select Name,Time
    $myobj.Name = ("$target [SOURCE]").ToUpper()
    $myobj.Time = 0.00
    $DCTable += $myobj
}

$name = "rTest" + (Get-Date -f MMddyyHHmmss)
Write-Host "`n  Creating Temp Contact Object [$name] on [$target]"
$contact = ([ADSI]"LDAP://$target/$ou").Create("contact","cn=$Name")
$contact.SetInfo()
$dn = $contact.distinguishedname
Write-Host "  Temp Contact Object [$dn] Created! `n"

$start = Get-Date

$i = 0

Write-Host "  Found [$($dclist.count)] Domain Controllers"
$cont = $true

While($cont)
{
    $i++
    $oldpos = $host.UI.RawUI.CursorPosition
    Write-Host "  =========== Check $i ===========" -fore white
    start-Sleep 1
    $replicated = $true
    foreach($dc in $dclist)
    {
        if($target -match $dc.Name){continue}
        $object = [ADSI]"LDAP://$($dc.Name)/$dn"
        if($object.name)
        {
            Write-Host "  – $($dc.Name.ToUpper()) Has Object [$dn]" (" "*5) -fore Green
            if($table -and !($dctable | ?{$_.Name -match $dc.Name}))
            {
                $myobj = "" | Select-Object Name,Time
                $myobj.Name = ($dc.Name).ToUpper()
                $myobj.Time = ("{0:n2}" -f ((Get-Date)$start).TotalSeconds)
                $dctable += $myobj
            }
        }
        else{Write-Host "  ! $($dc.Name.ToUpper()) Missing Object [$dn]" -fore Red;$replicated  = $false}
    }
    if($replicated){$cont = $false}else{$host.UI.RawUI.CursorPosition = $oldpos}
}

$end = Get-Date
$duration = "{0:n2}" -f ($end.Subtract($start).TotalSeconds)
Write-Host "`n    Took $duration Seconds `n" -fore Yellow

if($remove)
{
    Write-Host "  Removing Test Object `n"
    ([ADSI]"LDAP://$target/$ou").Delete("contact","cn=$Name")
}
if($table){$dctable | Sort-Object Time | Format-Table -auto}

11 Responses to “Check Active Directory Latency”

  1. on 28 Aug 2008 at 12:51 amAlan Renouf

    Very usefull, will hopefull get rid of all the replication worries.

  2. on 23 Aug 2009 at 6:42 amBryan Oakley

    Hi BSonPoSH

    I just wanted to say a million thanks for this superb bit of code..!
    It really is a very, very useful part of my AD toolkit now.

    Again thanks so much for *sharing* this with the rest of us…

    You rock..!

    cheers
    Bry

  3. on 25 Aug 2009 at 9:43 amtshell

    Thanks Bryan

  4. on 05 Oct 2009 at 12:07 pmJeremy

    Sorry for an ignorant question, but how do you actually run this?

  5. on 05 Oct 2009 at 12:17 pmtshell

    No problem 🙂

    Cut/paste into a file and just call it.

    c:\scripts\Test-AD.ps1

  6. on 27 Oct 2009 at 6:06 pmGreg Brown

    Hey B…
    This is a very nice piece of code. I have a couple usage questions if I may indulge you…

    1. Can I set the scope to the entire forest? I have a parent and 2 child domains.
    2. As the script ran, it found one of the two DC’s in the current scope. It successfully created the test contact on DC1, but I received an error from PS indicating that the object was not created on DC2. The count then got up to 400 and I believed it wasn’t going well, so I CTRL+C’d the script. Should I ignore the error? Should I wait longer for it to finish? (The object was created in AD, so the fact it wasn’t “created” on DC2 seems irrelevant.)

    Again, I appreciate any help you can lend.
    Thx in advance.
    gb

  7. on 27 Oct 2009 at 7:17 pmtshell

    Well good news bad news 🙂

    Bad News
    If you have more than ~30 DCs the script looses its affectiveness and there wasn’t much I could do about it. Also the current version only does Domain.

    Good News:
    I am working on Active Directory Replication Module [Powershell] which will do all of what your asking for.

  8. on 28 Oct 2009 at 6:46 amgreg

    I only have 2 dc’s in the current scope. How long should I let it run? Also, I get an error saying that the temp object was created on DC1, but not DC2. I can clearly see the object in the default users OU. Should I ignore that error?

  9. on 28 Oct 2009 at 7:10 amtshell

    Oh… that could be a bug or it could simply be just a replication schedule thing. If the DCs are in the same site or you have change notification enabled then it is clearly a bug else just wait 🙂

  10. on 17 May 2012 at 7:47 pmbaker_gt

    I like this script. Is there any way there could be a time out placed in it tho?

    I would love to use it with one of our tools, but if it doenst have a time out, it could run for ever.

    And how about exit codes? if it through an error code on edit this would REALLY allow this to be a great script!

  11. on 17 May 2012 at 7:57 pmtshell

    A timeout would be easy enough to add as well as exit codes.

Trackback this post | Feed on Comments to this post

Leave a Reply

You must be logged in to post a comment.