Friday, January 27, 2012

PowerShell DirSync Sample


Continuing with the PoC setup for the SQL Server MA, I want the flexibility to load the SQL data from either the authoritative text-file, or from a separate AD environment.  This will provide me the ability to test the MA in Dev and QA environments that are not as active as Production.  To do that, I want DirSync data from a source domain to use to populate the table.

Microsoft’s DirSync documentation has a sample in C++.  400+ lines of code!  And a very low percentage of the code volume is directly related to the search.  Yuck.  However, with some more Googling one can find that Brandon has a System.DirectoryServices.Protocols sample for PowerShell and the Israel Platforms PFE Team has a DirSync sample for C#.  Finally SANS had a nice overview on handling the Byte in PowerShell, which the DirSync cookie uses.

All the ingredients are assembled.  Combine and bake at 400° for 20 minutes and you get:

Add-Type -AssemblyName System.DirectoryServices.Protocols

If (Test-Path .\cookie.bin –PathType leaf) {
    [byte[]] $Cookie = Get-Content -Encoding byte –Path .\cookie.bin
} else {
    $Cookie = $null

$RootDSE = [ADSI]"LDAP://RootDSE"
$LDAPConnection = New-Object System.DirectoryServices.Protocols.LDAPConnection($RootDSE.dnsHostName)
$Request = New-Object System.DirectoryServices.Protocols.SearchRequest($RootDSE.defaultNamingContext, "(objectclass=*)", "Subtree", $null)
$DirSyncRC = New-Object System.DirectoryServices.Protocols.DirSyncRequestControl($Cookie, [System.DirectoryServices.Protocols.DirectorySynchronizationOptions]::IncrementalValues, [System.Int32]::MaxValue)
$Request.Controls.Add($DirSyncRC) | Out-Null

$MoreData = $true

while ($MoreData) {

    $Response = $LDAPConnection.SendRequest($Request)

    $Response.Entries | ForEach-Object {
        write-host $_.distinguishedName

    ForEach ($Control in $Response.Controls) {
        If ($Control.GetType().Name -eq "DirSyncResponseControl") {
            $Cookie = $Control.Cookie
            $MoreData = $Control.MoreData
    $DirSyncRC.Cookie = $Cookie

Set-Content -Value $Cookie -Encoding byte –Path .\cookie.bin

There you have it.  PowerShell DirSync in 27 lines of code!

[Edit 2012.02.20: optimized while loop]


  1. Works well, thank you, you saved me hours of work...

  2. Thank you - you rock!

    You allowed me to quickly answer this question for myself and others.