Use PowerShell to Find Where the Current FSMO Roles are Assigned in Active Directory

A while back, I had a need to figure out with PowerShell what server in an Active Directory domain held the PDC Emulator FSMO Role. I found a script on a very popular blog site that figured it out by using a command similar to this:

1Get-ADDomainController -Filter * |
2Where-Object OperationMasterRoles -contains PDCEmulator |
3Select-Object -Property Name

fsmo-roles1.png

While it accomplished what was necessary, I immediately thought "I can do better" and improved the one liner so it filtered left:

1Get-ADDomainController -Filter {
2  OperationMasterRoles -like 'PDCEmulator'
3} | Select-Object -Property name

fsmo-roles2.png

At the April Philadelphia PowerShell User Group meeting, I won a copy of Managing Active Directory with Windows PowerShell written by Jeff Hicks and published by SAPIEN Technologies.

On page 90, I noticed one of the examples used the Get-ADDomain cmdlet to retrieve which server held the PDC Emulator role so it was time to investigate that cmdlet.

What I discovered is all of the domain level FSMO roles could be retrieved very easily using that cmdlet:

1Get-ADDomain |
2Select-Object -Property InfrastructureMaster, PDCEmulator, RIDMaster

fsmo-roles3.png

A little more research and I found that the Get-ADForest cmdlet could be used to obtain the server names of the forest level FSMO role holders:

1Get-ADForest |
2Select-Object -Property DomainNamingMaster, SchemaMaster

fsmo-roles4.png

I wrote a function named Get-FSMORole that will retrieve the FSMO roles holders from the domain of the current user that this function is being run by, or from domains that are provided via pipeline or parameter input as shown in the following examples:

 1function Get-FSMORole {
 2  [CmdletBinding()]
 3  param(
 4    [Parameter(ValueFromPipeline=$True)]
 5    [string[]]$DomainName = $env:USERDOMAIN
 6  )
 7  BEGIN {
 8    Import-Module ActiveDirectory -Cmdlet Get-ADDomain, Get-ADForest -ErrorAction SilentlyContinue
 9  }
10  PROCESS {
11    foreach ($domain in $DomainName) {
12      Write-Verbose "Querying $domain"
13      Try {
14      $problem = $false
15      $addomain = Get-ADDomain -Identity $domain -ErrorAction Stop
16      } Catch { $problem = $true
17      Write-Warning $_.Exception.Message
18      }
19      if (-not $problem) {
20        $adforest = Get-ADForest -Identity (($addomain).forest)
21
22        New-Object PSObject -Property @{
23          InfrastructureMaster = $addomain.InfrastructureMaster
24          PDCEmulator = $addomain.PDCEmulator
25          RIDMaster = $addomain.RIDMaster
26          DomainNamingMaster = $adforest.DomainNamingMaster
27          SchemaMaster = $adforest.SchemaMaster
28        }
29      }
30    }
31  }
32}

fsmo-roles5a.png

This function depends on either having the Remote Server Administration Tools installed or importing the Active Directory module locally via Implicit Remoting before running the function. In the previous example, the machine the function is being run on is running Windows 8 and the domain controllers are running Windows Server 2012, although I've tested it on a multiple Windows Server 2008 R2 forests where there's a trust between the forests and the function worked without issue.

µ