Powershell Script to request info about state of AD Site links

Hi guys,

I read an interesting post in the Ashled McGlone blog that I think is good to remark.

See you!



Author’s note:  Before you dismiss this article you should know that the top two areas where I find issues for AD health are replication and DNS.  If you’re short on time skip to the bottom section “But Wait… There’s More” and run that report in your environment.  Otherwise I think you’ll get a lot of value from this content.

Freaky Neat

MonkIn my role as a Microsoft Premier Field Engineer I get to see what our customers do with Active Directory, both good and bad. Some admins are neat freaks about keeping everything pretty. (Imagine Adrian Monk as an AD admin.)  Others barely have time to open Facebook at work, and neatness is not a priority. Those are just the facts of IT life.  Consequently one area we frequently clean up is AD replication. You can see my former articles here on cleaning up replication settings.

What is hiding in your site links?

Today’s post will help you clean up site link descriptions and give you some nice reporting capability. For a quick overview of the terminology you can read the landmark TechNet article How Replication Works. To make a long story short admins create sites and then link them together with site links. Like most things in life change happens, and we don’t go back to clean up afterwards. I commonly find orphaned site links, mondo links with too many sites, and site link descriptions that haven’t been updated to reflect their member sites. (Use the free AD Topology Diagrammer to get a really cool Visio diagram of your sites and links.)

Some folks like to set their site link description field to list each of the member sites in the link. If that is you, then you’ll love this script.  Today’s script enumerates all of the member sites in a site link and then concatenates their names into the description of the site link.  Also, it will make a note in the description for any site links that have change notification enabled.  Now that’s handy!

Here is a screenshot from my lab showing what the descriptions can look like:


The Code

First let’s list the sitelinks:

# List all sitelinks            
Get-ADObject -LDAPFilter '(objectClass=siteLink)' ` 
    -SearchBase (Get-ADRootDSE).ConfigurationNamingContext ` 
    -Property Name, Cost, Description, Sitelist |            
    Format-List Name, Cost, Description, Sitelist

Now let’s update the descriptions:

# One ridiculous line of code            
# Broken down for readability            
Get-ADObject -LDAPFilter '(&(objectClass=siteLink)(siteList=*))' ` 
    -SearchBase (Get-ADRootDSE).ConfigurationNamingContext ` 
    -Property Name, Cost, Sitelist, Options |            
    ForEach {            
        Set-ADObject -Identity $_.DistinguishedName -Replace @{            
                ForEach ($site in $_.sitelist) {            
                    $s += "$($site.SubString(3,$site.IndexOf(",")-3)) <--> "            
                If ($_.Options -band 1) {' (Notify)'}            

Some site links have been orphaned and emptied by deleting the member sites and forgetting to delete the associated site link. For those here is a modified line that will update their description to ‘EMPTY SITE LINK’.

# Flag empty site links            
Get-ADObject -LDAPFilter '(&(objectClass=siteLink)(!siteList=*))' ` 
    -SearchBase (Get-ADRootDSE).ConfigurationNamingContext ` 
    -Property Name, Sitelist, Options |            
    % {Set-ADObject -Identity $_.DistinguishedName ` 
    -Replace @{Description='EMPTY SITE LINK'+` 
    $(If ($_.Options -band 1) {' (Notify)'})}}

The real magic in these lines are the LDAP filters:

  • All sitelinks: ‘(objectClass=siteLink)’
  • Sitelinks with member sites: ‘(&(objectClass=siteLink)(siteList=*))’
  • Sitelinks without member sites: ‘(&(objectClass=siteLink)(!siteList=*))’

Once you have imported the ActiveDirectory module you can type Get-Help about_ActiveDirectory_filter for more information on creating LDAP filter syntax.

But wait… there’s more!

In the script file attached at the end of the post I have included all of the scripts above plus some bonus content.  There is a site report script that will give you some schweet stats on your AD sites.  Use it to find those sites that are not in a site link, missing subnets, or do not have a DC.  The output looks like this:

Name     SiteLinkCount SubnetCount DCCount IsEmpty WhenCreated  Description
----     ------------- ----------- ------- ------- -----------  -----------
Bogus1               1           0       0    True 10/6/2010    Test site
Bogus2               0           0       0    True 1/25/2011    Test site
Bogus3               0           0       0    True 1/25/2011    Test site
Kentucky             3           1       2   False 4/13/2010    Kentucky
Lonely               2           1       1   False 2/17/2011    Remote site
Ohio                 2           2       2   False 4/13/2010    Ohio

Armed with this handy little report you will know where to begin your site, subnet, and site link remediation activities.

The Fine Print

This version of the script works with PowerShell v2 in your environment today. In AD PowerShell v3 there are new cmdlets to work with site links directly.

If you’re one of those who likes to note WAN speeds on site link descriptions, then you have a couple options:

  • Don’t run the script. It will overwrite your notes in the descriptions.
  • Export the descriptions, run this script, then manually add back the WAN speeds.

Unless you schedule this script to run as a scheduled task, you’ll need to run it again any time you update sites or site links. The descriptions are only as good as the last run of the script.

Currently the script inserts ‘<–>’ between the site names. Feel free to edit this to your liking.

If you have 1,000,000,000 sites jammed into a single site link, then it is likely that the concatenated description string will be too long and break the script.  Don’t do that if you can avoid it.

Running this script is harmless to your environment’s functionality, but it will overwrite your existing site link descriptions. As always you should test it in a lab first.



Virtual Domain Controller Cloning in Windows Server 2012


Reading the Ask Premier Filed Engineering Platforms Blog I find a very interesting post that show how with Windows Server 2012 you can clone a DC!




Tom Moser here with a post on one of the new ADDS features in Windows Server 2012; Virtual Domain Controller Cloning.

Until now, cloning, snapshotting, copying, or pretty much doing anything but rebuilding from scratch to a virtual domain controller wasn’t just unsupported; it had the potential to be really bad for your directory. Cloning or restoring snapshots of DCs could result in USN rollbacks or lingering objects, just to name a couple of problems.

Starting in Windows Server 2012, we now support DC cloning as well as snapshot restoration of domain controllers. With the RTM bits available, I found myself rebuilding my lab and took the opportunity to document the process to demonstrate just how easy it is to clone virtual domain controllers with Windows Server 2012.


There are a few base infrastructure requirements to take advantage of DC cloning.

  • The hypervisor must support VM-GenerationID. Hyper-V running on Windows Server 2012 supports this feature. Other virtualization vendors will have the ability to implement this as well, so check with your vendor to see if it’s supported.
  • The source virtual DC must be running Windows Server 2012.
  • The PDC emulator role holder must be online and available to the cloned DC and must be running Windows Server 2012.

There are a few other steps and requirements and I’ll take you through those now.

Cloneable Domain Controllers Group

There’s a new group in town. It’s called Cloneable Domain Controllers and you can find it in the Users container. Membership in this group dictates whether a DC can or cannot be cloned. This group has some permissions set on the domain head that should not be removed. Removing these permissions will cause cloning to fail. Also, as a best practice, DCs shouldn’t be added to the group until you plan to clone and DCs should be removed from the group once cloning is complete. Cloned DCs will also end up in the Cloneable Domain Controllers group. Make sure to remove those as well.

In the case of my lab, I planned to build out a whole bunch of Server Core DCs. I built a single DC running the GUI-enabled version of Server, then built a DC running Server Core. This DC, DC02, will be my source domain controller.

The first step in the cloning process is to add the source DC to the Cloneable Domain Controllers group. Here, I’ve used the latest version of Active Directory Administrative Center to add my DC to the group. Make sure to select “Computers” under Object Type in the object picker when adding the DC. Here, I verified that the group now contains my source DC, DC02. (Figure 1).

We’re almost there. No kidding. Next, we need to create the config file.


There’s one key difference between a cloned DC and a DC that is being restored to a previous snapshot: DCCloneConfig.XML.

DCCloneConfig.xml is an XML configuration file that contains all of the settings the cloned DC will take when it boots. This includes network settings, DNS, WINS, AD site name, new DC name and more. This file can be generated in a few different ways.

  • The New-ADDCCloneConfig cmdlet in PowerShell
  • By hand with an XML editor
  • By editing an existing config file, again with an XML editor (Notepad is not an XML editor.)

In my lab, I used the PowerShell cmdlet to generate the config. This is an easy, safe way to generate the file and ensures there won’t be any issues during cloning.

On your Windows Server 2012 domain controller, fire up PowerShell. From there, take a minute to run Get-Help New-ADDCCloneConfig –Full and review the help page.

Now that you’ve thoroughly reviewed the help page, let’s go through the steps. On DC02, I ran the following:

New-ADDCCloneConfigFile -IPv4Address -IPv4DefaultGateway -IPv4SubnetMask255.255.255.0 -IPv4DNSResolver, -Static -SiteName CORPDR

This cmdlet will generate a config XML using the specified parameters, in this case IP information, AD site to use, and that it’s a static IP configuration. The IP information provided to the cmdlet will be used by the new cloned domain controller when it begins cloning.

The cmdlet is going to do a few things prior to generating the configuration XML file. First, it’s going to verify that the PDC is available and running Windows Server 2012 or later (one of the pre-reqs above). This check can be skipped by specifying the –Offline switch. You should only need to do this if a global catalog isn’t available. Second, it’s going to verify that the source DC (where you’re running the cmdlet) is a member of the Cloneable Domain Controllers group. Finally, the cmdlet is going to check the DC for applications that may not support cloning. If any applications or services are detected (such as DHCP), generation of the config will fail. You’ll see something like Figure 2 (below).

Figure 2 – Failed Clone Config Generation

The cmdlet warning text is pretty helpful. It tells us that applications were found that are not on the allowed list. What’s on the allowed list? Good question. You can find it at C:\Windows\System32\DefaultDCCloneAllowList.xml. This list exists by default on Windows Server 2012 domain controllers and should not be modified. If you want to add a discovered application to the list, you’ll need to generate a custom DC allow list.

Prior to generating the custom allow list, you’ll want to review what applications actually caused the warning. Running Get-ADDCCloningExcludedApplicationList (tab complete is your buddy here) will show you that list. This cmdlet will dump out all of the services that were discovered while trying to generate the DCCloneConfig.XML (Figure 3). From here, you can make a decision; remove the discovered application or service or add the application to the custom allow list. Generally speaking, if it’s a Microsoft service that has been flagged, as DHCP has been flagged in this example, you should not clone it. If a third party application is discovered and you’ve verified with the vendor that cloning is supported, then you can jump to Figure 4.

You’ve verified with the application vendor that the service is OK to clone. Generating the allow list is easy. Run Get-ADDCCloningExcludedApplicationList again, but specify the –GenerateXML switch.

The cmdlet generates the XML and writes it out to c:\windows\ntds, as the output shows. Viewing the contents in notepad shows this (Figure 5):

Figure 5 – Or you should just remove DHCP…

And that’s what the custom allow list looks like. Again, you could use an XML editor to modify this, but should probably remove the application unless you have a specific reason to create a clone of the service and you’ve verified that the application supports cloning. Once you’ve generated the XML file, you can run New-ADDCCloneConfigFile again and it’ll successfully generate your config. In my case, I used Remove-WindowsFeature and removed DHCP from my DC. Figure 6 shows the PowerShell commands for both removing DHCP as well as successfully generating my DCCloneConfig.

Figure 6 – That’s a lot of green, so I think it’s OK.

As the output shows, the XML file is written to c:\windows\ntds. That’s one of three valid locations where the file can be placed for cloning. All three locations are:

  • %windir%\NTDS
  • Wherever the DIT lives (if you’ve changed the path to D:\NTDS, for example)
  • The root of any removable media

The config file should have been written out to c:\windows\ntds. Viewing the content with Get-Content in PowerShell shows us what the config looks like (Figure 7). If you’re familiar with XML-based configuration files, this should look pretty typical.

Now I’ve got the config file, I’ve removed the unsupported service and I’m ready to start the cloning process.

Copying the Source DC

The last step now is to export the source virtual machine. This can be accomplished via PowerShell or the Hyper-V management console.

First, turn off the source DC then export the VM. I used PowerShell (Figure 8). Milt0rDC02 is the name I used in Hyper-V forDC02.

Now that I’ve exported the source DC, I need to import the VM. In PowerShell, I navigate to the path were I exported the VM and to the Virtual Machines subdirectory. There, I run Import-VM and store the result in a variable called $clonedVM.Milt0rDC03 is the name in Hyper-V I’ll use for this new domain controller.

    $clonedVM = Import-VM –Path <VM XML Path>.xml –Copy –GenerateNewId –VhdDestinationPathG:\VHDs\Milt0rDC03

With the Import-VM cmdlet (Figure 9), I specify the path to the VM XML file and use the –Copy and –GenerateNewIdswitches. The copy switch is going to leave my original export intact and the GenerateNewId switch will generate a VM ID that differs from the ID of the originally exported machine. I also had to specify a different VHD path using –VhdDestinationPath. This path is the directory where the VHD will be copied to. The VHD will import using the same name as the VHD from the export. In my case, this was Milt0rDC02.vhdx. The copied VHD will import toG:\VHDs\Milt0rDC03\Milt0rDC02.vhdx. These can be renamed and the VM reconfigured after the import is complete. You could also simply create a copy of the VHD, rename it, create a new VM, then attach the VHD to the new VM.

Once that completes, I’m able to quickly rename the VM (as it will retain the name of the originally exported VM) by using the Rename-VM cmdlet (see Figure 9).

That’s it. From here, it’s just a matter of turning on the DC and letting everything happen on its own.


If you’ve made it this far in the post, you’re probably thinking “this seems pretty long and drawn out.” Sure, I’m pretty long-winded, but we’ve actually only done two things here: Create a clone config file (which is fast, assuming you don’t have any apps that aren’t allowed) and create a copy of the source DC. Now we can power on the copied DC, our clone, and the rest should take care of itself.

I fire up the VM and after a minute or so of “Completing installation” I see this screen (Figure 10).

A few minutes of this and the DC will reboot. When it’s up, you should see a new DC in the Domain Controllers OU and logging in to the DC should indicate that you’re in normal mode and not DSRM. Now you’ll want to take some time to verify that both NTDS and SYSVOL replication are working properly and that everything is responding as expected. If it checks out, you’ve successfully cloned your virtual domain controller.


At the beginning of the post, I mentioned that the hypervisor must support VM-GenerationID. VM-GenerationID is a property that is exposed to the VM via the virtualization drivers and is unique to that virtual machine. Each Windows Server 2012 domain controller stores its own VM-GenerationID in a property called msDS-GenerationId on the DC’s computer object. This value does not replicate. If you try to view the value of msDS-GenerationId from another DC, you’ll see that the value shows up as not set.

Figure 11, below, shows the value on DC02-CL0001. I had to connect directly to that DC in ADUC to see the value.

Each time a Windows Server 2012 domain controller boots, it compares the VM-GenerationID presented by the hypervisor to the value it has stored in the DIT. If they match, it boots normally. If they don’t match, this indicates that the DC is a restored snapshot or a clone.

How does it determine if the VM is a restored snapshot or a clone?

Remember that DCCloneConfig.xml we created earlier? When the VM-GenerationID mismatch is detected, the next step is to check for that configuration file. If it exists, the cloning process starts. If that file doesn’t exist, it’s assumed that this is a restored snapshot and the restore process starts.

After, there’s a bunch of “stuff” that happens which, for the sake of brevity, I’ll cover in another post. The DC reads the config, modifies the domain controller configuration based on the settings in the DCCloneConfig.xml, and attempts to complete the cloning process. Here’s where you might run in to issues, especially if you cheated and just dropped a config on another server without running the New-ADDCCloneConfig cmdlet. Some problems you might run in to are:

  • PDC is unavailable or not running Server 2012. I actually ran in to this because I neglected to change my virtual switch in Hyper-V.
  • You thought you were being sneaky and dropped a config file on to a clone source VHD with apps that are not in the default allowed list, without adding a custom allow list. This is checked during cloning and will cause the clone to fail.
  • A duplicate IP is detected.

In each of those cases, the clone will fail and the DC will boot to Directory Services Restore Mode. Logging on to the DC and viewing the DCPromo.log file in C:\Windows\Debug should give you some hints on why it failed.

Assuming you didn’t run in to any of those issues and your DC clone completed successfully, you’re all done! If you didn’t specify the –CloneComputerName parameter when you ran New-ADDCCloneConfig (which I intentionally left out), the DC will boot using a generated name. If you do specify that parameter, the given name will be used for the new domain controller. In the screenshot above (Figure 11), you can see that my DC is called DC02-CL0001. The source DC was called DC02. The cloning process will take the first eight characters of the source domain controller’s name then append –CL000X. This value will count up for each clone. Once you get to 9999, you’ll need to pick a new name to clone immediately followed by calling your TAM to brag about having 10,000 domain controllers. Since I don’t plan on continuing to clone, I decided to rename the domain controller to DC03 and called it a day.


If you’ve made it this far, you’ll now be able to successfully clone DCs in your environment. After each time through cloning, I mounted the exported VHD from the source VM, modified the DCCloneConfig.xml file, and created another copy of the VM. This process enabled me to very quickly create four copies of my original Server Core DC. I’ll demo that in a future post.

I hope this post gives you an understanding of virtual domain controller cloning and the steps involved to make it work. In a near-future post, I’ll cover the process with a little more depth as well as troubleshooting and safe restore. Thanks for reading!

-Tom Moser

How to know if a 2008 R2 Domain Controller was well promoted

When you promote a 2008 r2 to domain controller a good practice is to do a diagnostic of all domain controller before and test after that new DC 2008 R2 too.

Dcdiag /a

Dcdiag /q

Repadmin /showrepl

Confirm that the DFS Replication and Net logon services are started and with automatic mode.

From a cmd execute a net share and view the sysvol and netlogon shared folders

  • SYSVOL  en %systemroot%\SYSVOL\sysvol\
  • NETLOGON en %systemroot%\SYSVOL\sysvol\<Dominio>.domain\SCRIPTS

If not appear run dcdiag /test:replications and dcdiag /test:netlogons

dcdiag /test:dns

dcdiag /test:MachineAccount

dcdiag /s:<DomainControllerName> /test:knowsofroleholders /v

dcdiag /s:<DomainControllerName> /test:fsmocheck

GPOs do not replicate – Event id 1006 when migrating from AD 2003 to 2008 R2

If when migrating from 2003 to 2008 R2 AD and one 1006 event appears in the eventivewr (DCs was causing the new Windows 2008 does not properly get your computer GPOs) is solved by installing the following hotfix on Windows 2003 DCs:


Apparently this problem may be that in the past ​​an authoritative restore of the domain was make and, according to the KB, this causes a KDC problem.