11 November, 2012

Get list of GCs - Active Directory


Ok, here is the next bit. I have many domain controllers (DC) in an Active Directory forest and need to know which domain controller is a Global Catalog (GC). Read it carefully: it's not enough to list which DCs have the GC flag set, I need to know which DC is properly advertised as a GC. Why? Because having enough number of healthy GCs in a forest is essential for Exchange Address Book lookups and for Universal Group membership caching. And again, you can activate the GC flag in dssite.msc many times, if you have an AD database with size of 10+ GB, it will take time to get all the global catalog data built up and replicated across.

Obviously, if you had 2 DCs, you could look into the eventlog and see if there's any eventid 1126 in the log, but doing it every day with every domain controller, after reboot...nah, you don't want to go down that way.

First, let's get the list of DCs in a particular domain. There are many ways to do this, i.e. if you don't have Windows 2008 in your environment , you can do this:
([System.DirectoryServices.ActiveDirectory.DomainController]::findall((new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain","tatooine.com"))))

If you have 2008 DCs:
import-module ActiveDirectory
$DCs = Get-ADDomainController -filter * -DomainName tatooine.com

To list which DC is advertised as a GC, you can use the isGlobalCatalogReady RootDSE attribute, on Windos 2003 DCs:
gc dcs.txt | %{$p="" | select ComputerName,Is_GC; $p.ComputerName=$_; $p.Is_gc=(([adsi]("LDAP://" + $_ + "/RootDSE")).isGlobalCatalogReady); $p}


On Windows 2008 DCs:
$GCs = Get-ADDomainController -filter { IsGlobalCatalog -eq $True}

Let's combine this with checking which DC should really be a GC, so where the GC flag is set and have a full list of DCs with the two parameters:
- GC flag's status on the server
- Is GC ready flag on the server

$objColl = @(); $DCs | %{
   # create object with 3 properties   $psObj = "" | select ComputerName,Is_GC_Ready,Is_GC_set
   $psObj.ComputerName = $_     # get if the particular DC is advertised as a GC
   $RootDSE = ([adsi]("LDAP://" + $_ + "/RootDSE"))
   $psObj.Is_gc_ready = $RootDSE.isGlobalCatalogReady
     # enumerate the GC flag of the server
   $ntdsObj = $RootDSE.Get('dsServiceName')
   $psObj.Is_gc_set = ([adsi]"LDAP://$_/$ntdsObj").Get('options')
     $objColl += $psObj
   $psObj}

The object collection can be filtered afterwards, i.e. I want to know the list of DCs which have GC flag set but they are not advertised as GCs:
$objColl | ?{($_.Is_GC_set -eq 1) -and ($_.Is_GC_Ready -eq $false)}

Or list the DCs which do not have the GC flag set:
$objColl | ?{($_.Is_GC_set -eq 0)

Feel free to edit it and experiment with the ActiveDirectory cmdlets on Windows 2008 (Get-ADDomainController)

Clipboar friendly code:
$objColl = @(); 
$DCs | %{ 
  
      # create object with 3 properties
      $psObj = "" | select ComputerName,Is_GC_Ready,Is_GC_set
      $psObj.ComputerName = $_
  
      # get if the particular DC is advertised as a GC
      $RootDSE = ([adsi]("LDAP://" + $_ + "/RootDSE"))
      $psObj.Is_gc_ready = $RootDSE.isGlobalCatalogReady
  
      # enumerate the GC flag of the server
      $ntdsObj = $RootDSE.Get('dsServiceName')
      $psObj.Is_gc_set = ([adsi]"LDAP://$_/$ntdsObj").Get('options')
  
      $objColl += $psObj
      $psObj
}  

May the force...
t

No comments:

Post a Comment