Metadata associated with Active Directory Replication is exposed in AD via many constructed attributes. Some of these metadata attributes come in pairs of binary blob & xml representation of the metadata element.

Constructed Replication XML Metadata Attribute

Available on Objects

Corresponding Binary Attribute

msDS-ReplQueueStatistics

Root DSE

-

msDS-ReplAllInboundNeighbors

Root DSE

-

msDS-ReplAllOutboundNeighbors

Root DSE

-

msDS-NCReplCursors

NC Head

replUpToDateVector

msDS-NCReplInboundNeighbors

NC Head

repsFrom

msDS-NCReplOutboundNeighbors

NC Head

repsTo

msDS-ReplAttributeMetaData

All Objects

replPropertyMetaData

msDS-ReplValueMetaData

All Objects

-

For the Inspecting Deleted Objects before Restore blog post script, I had parsed the msDS-ReplAttributeMetaData attribute of the deleted objects to determine the actual deleted time of the objects. I had found the parsing so simple to do using ADPowerShell, that I decided to write about it in this separate post.

This post is focused on the msDS-ReplAttributeMetaData attribute … but the technique shown here can be used to parse all of the above listed XML format attributes …

Let’s start by a simple Get-ADObject call and requesting the msDS-ReplAttributeMetaData attribute.

Get-ADObject "DC=DUGILL,DC=DEMO" -Properties "msDS-ReplAttributeMetaData"

Simple Get-ADObject with msDS-ReplAttributeMetaData

Let’s store the xml string value in a local variable so that we can play with it without cluttering the commandline. Now, the attribute name has a hyphen (‘-’) in it so we will need to help the powershell parser and put quotes around the attribute name.

$xmlAttribute = (Get-ADObject "DC=DUGILL,DC=DEMO" -Properties "msDS-ReplAttributeMetaData")."msDS-ReplAttributeMetaData"

Above we see that the xml text from the attribute is not a valid xml string, as it does not have a root tag. So let’s add a root tag to it.

$xmlAttribute = “<root>” + $xmlAttribute + “</root>”

Now that we’ve made our msDS-ReplAttributeMetaData attribute value a valid xml string, comes the turn of some PowerShell magic. PowerShell makes it really simple to convert XML string to an XML Document Object (a form which can be worked on programmatically in a simpler way …)

SO, let’s go ahead and cast the string into an XML Document object.

$xmlAttributeDocObject = [xml] $xmlAttribute # wow … it’s that simple

Null Charecter Error

Ok not that simple … we hit a pretty nasty looking parsing error. The error is because the XML string contains some ASCII null characters (a bug in AD). So how do we get rid of these null charecters?

The hint is in the error which says the char has a hex value of 0x00 which is basically decimal 0. Can I use String.Replace function to get rid of these characters? As it turns out – I can …

String.Replace takes two arguments: first, the char or string to replace and second, the char or string to replace with. Note I’m using PowerShell casting again, to convert the hex value 0x00 to a char value. Replacing all occurrences of ascii nulls in the string with a space char (“ ”) …

$xmlAttribute = $xmlAttribute.Replace([char]0,” ”)

Now let’s try converting it into the XML Doc Object again … this time it works!!

$xmlAttributeDocObject = [XML]$xmlAttribute

Let’s inspect the xml doc object and admire the wonderful XML experience provided by PowerShell :)

Inspecting XML Doc Object

And finally $xmlAttributeDocObject.root.DS_REPL_ATTR_META_DATA | ft #… viola!

BTW, this output had got me wondering if I had just typed repadmin /showmeta …

Inspecting XML Doc Object - Repadmin Like Output

Focusing on selected interesting XML elements …

$xmlAttributeDocObject.root.DS_REPL_ATTR_META_DATA | ft pszAttributeName,ftimeLastOriginatingChange,pszLastOriginatingDsaDN

Inspecting XML Doc Object - FT Selected Attributes

We see that the originating change time is in the Zulu time format and the originating dc’ NTDS Settings object DN is what is available … with some format transforms we can get to a better looking output

$ObjectMetadataTableFormatter = @()

$ObjectMetadataTableFormatter += @{Label="Attribute LDAP Name"; Expression={$_.pszAttributeName}}

$ObjectMetadataTableFormatter += @{Label="Originating DC"; Expression={(Get-ADObject $_.pszLastOriginatingDsaDN.Substring(17,$_.pszLastOriginatingDsaDN.length-17) -properties dnshostname).DNSHostName}}

$ObjectMetadataTableFormatter += @{Label="Originating Change Time"; Expression={[datetime]::parse($_.ftimeLastOriginatingChange)}}

$xmlAttributeDocObject.root.DS_REPL_ATTR_META_DATA | ft $ObjectMetadataTableFormatter

Inspecting XML Doc Object - Using Table Formatter

You may also use the attached script function (or add it into your function profile script). The function allows pipelining objects from other Get-AD cmdlets to fetch the object replication metadata …

Using the function

enjoy!

Dushyant Gill

Program Manager - Microsoft