Hey, Scripting Guy! Question Hey, Scripting Guy! I need to use Windows PowerShell 2.0 to search Active Directory Domain Services (AD DS) to retrieve information about my Windows Server 2008 and Windows Server 2008 R2 domain controllers. I am specifically interested in determining the holders of the special FSMO roles in AD DS. Is this something I can do natively within Windows PowerShell 2.0? I have seen various cmdlets mentioned on the Internet, but that would involve downloading and installing separate software, which is something I am not inclined to do. I have also seen scripts that use ADSI from within Windows PowerShell, but they seem rather complicated. Does Microsoft make AD DS cmdlets?

-- MP

 

Hey, Scripting Guy! Answer Hello MP,

Microsoft Scripting Guy Ed Wilson here. I have been rather busy this week collecting addresses for all of our Official Scripting Guys Forum moderators. Because these guys are all volunteers, and because they all do a great job answering questions on the forum, Craig and I wanted to do something nice for them. Without a budget, there was not a whole lot we could do, but we were able to scare up a little token of our appreciation. I wanted to give each of them a new car with the Dr. Scripto logo painted on the hood, and the Windows PowerShell logo painted on each door. However, it would have cost too much for the custom paint job, so we decided to go with…wait, that is still a secret. The moderators all read the Hey, Scripting Guy! Blog on a daily basis, and therefore I do not want to spoil the surprise.

One of our moderators, Shane, is from Queensland in Australia. The Scripting Wife and I have been to Brisbane several time, and we started reminiscing last night as we were compiling the mailing list. We would love to go back to Brisbane once my ear clears up and I am able to fly again. I could speak to the Brisbane PowerShell Users Group, and load up my suitcase with ANZAC biscuits. Here is one of my favorite pictures from Brisbane.

Photo of Brisbane, Australia

MP, Microsoft made AD DS Windows PowerShell cmdlets available with Windows Server 2008 R2. When you have one domain controller running Windows Server 2008 R2 in your domain, you can use the new cmdlets to manage your AD DS installation. To make the cmdlets available on the Windows 7 desktop, the cmdlets are available via the Remote Server Admininistration Tools (RSAT). For more information about the AD DS cmdlets, see What’s Up with Active Directory Domain Services Cmdlets? The AD DS cmdlets ship in a Windows PowerShell module, and you may therefore be interested in the Get-MyModule function from the Weekend Scripter article, Checking for Module Dependencies in Windows PowerShell. A good example of using that function can be seen in the Hey, Scripting Guy! post, Can I Use Group Policy Cmdlets to Test Active Directory Replication?

MP, to find information about domain controllers and FSMO roles, you do not have to write a Windows PowerShell script; you can do it directly from the Windows PowerShell console or ISE using the Active Directory cmdlets. The first thing that needs to done is to load the ActiveDirectory module into the current Windows PowerShell session. Though it is possible to add the Import-Module cmdlet to your Windows PowerShell profile, in general it is not a good idea to load a bunch of modules that you may or you may not use on a regular basis. In fact, you can load all the modules at once by piping the results of the Get-Module –listavailable command to the Import-Module cmdlet. This is shown here:

 

PS C:\> Get-Module -ListAvailable | Import-Module
PS C:\> Get-Module
ModuleType Name ExportedCommands
---------- ---- ----------------
Script BasicFunctions {Get-ComputerInfo, Get-OptimalSize}
Script ConversionModuleV6 {ConvertTo-Feet, ConvertTo-Miles, ConvertTo-...
Script PowerShellPack {New-ByteAnimationUsingKeyFrames, New-TiffBi...
Script PSCodeGen {New-Enum, New-ScriptCmdlet, New-PInvoke}
Script PSImageTools {Add-CropFilter, Add-RotateFlipFilter, Add-O...
Script PSRss {Read-Article, New-Feed, Remove-Article, Rem...
Script PSSystemTools {Test-32Bit, Get-USB, Get-OSVersion, Get-Mul...
Script PSUserTools {Start-ProcessAsAdministrator, Get-CurrentUs...
Script TaskScheduler {Remove-Task, Get-ScheduledTask, Stop-Task, ...
Script WPK {Get-DependencyProperty, New-ModelVisual3D, ...
Manifest ActiveDirectory {Set-ADOrganizationalUnit, Get-ADDomainContr...
Manifest AppLocker {Get-AppLockerPolicy, Get-AppLockerFileInfor...
Manifest BitsTransfer {Start-BitsTransfer, Remove-BitsTransfer, Re...
Manifest FailoverClusters {Set-ClusterParameter, Get-ClusterParameter,...
Manifest GroupPolicy {Get-GPStarterGPO, Get-GPOReport, Set-GPInhe...
Manifest NetworkLoadBalancingCl... {Stop-NlbClusterNode, Remove-NlbClusterVip, ...
Script PSDiagnostics {Enable-PSTrace, Enable-WSManTrace, Start-Tr...
Manifest TroubleshootingPack {Get-TroubleshootingPack, Invoke-Troubleshoo...
PS C:\>

Once you have loaded the ActiveDirectory module, you will want to use the Get-Command cmdlet to see the cmdlets that are exported by the module. This is shown here:

 

PS C:\> Get-Module -ListAvailable
ModuleType Name ExportedCommands
---------- ---- ----------------
Script BasicFunctions {}
Script ConversionModuleV6 {}
Script DotNet {}
Manifest FileSystem {}
Manifest IsePack {}
Manifest PowerShellPack {}
Manifest PSCodeGen {}
Manifest PSImageTools {}
Manifest PSRSS {}
Manifest PSSystemTools {}
Manifest PSUserTools {}
Manifest TaskScheduler {}
Manifest WPK {}
Manifest ActiveDirectory {}
Manifest AppLocker {}
Manifest BitsTransfer {}
Manifest FailoverClusters {}
Manifest GroupPolicy {}
Manifest NetworkLoadBalancingCl... {}
Manifest PSDiagnostics {}
Manifest TroubleshootingPack {}
PS C:\> Import-Module active*
PS C:\> Get-Command -Module active*
CommandType Name Definition
----------- ---- ----------
Cmdlet Add-ADComputerServiceAccount Add-ADComputerServiceAccount [...
Cmdlet Add-ADDomainControllerPasswordR... Add-ADDomainControllerPassword...
Cmdlet Add-ADFineGrainedPasswordPolicy... Add-ADFineGrainedPasswordPolic...
Cmdlet Add-ADGroupMember Add-ADGroupMember [-Identity] ...
Cmdlet Add-ADPrincipalGroupMembership Add-ADPrincipalGroupMembership...
Cmdlet Clear-ADAccountExpiration Clear-ADAccountExpiration [-Id...
Cmdlet Disable-ADAccount Disable-ADAccount [-Identity] ...
Cmdlet Disable-ADOptionalFeature Disable-ADOptionalFeature [-Id...
Cmdlet Enable-ADAccount Enable-ADAccount [-Identity] <...
Cmdlet Enable-ADOptionalFeature Enable-ADOptionalFeature [-Ide...
Cmdlet Get-ADAccountAuthorizationGroup Get-ADAccountAuthorizationGrou...
Cmdlet Get-ADAccountResultantPasswordR... Get-ADAccountResultantPassword...
Cmdlet Get-ADComputer Get-ADComputer -Filter <String...
<output truncated>

To find a single domain controller, if you are not sure of one in your site, you can use the –discover switch on the Get-ADDomainController cmdlet. One thing to keep in mind is that the –discover parameter could return information from the cache. If you wish to ensure that a fresh discover command is sent, use the –forceDiscover switch in addition to the –discover switch. This is shown here:

 

PS C:\> Get-ADDomainController -Discover
Domain : NWTraders.Com
Forest : NWTraders.Com
HostName : {HyperV.NWTraders.Com}
IPv4Address : 192.168.1.100
IPv6Address :
Name : HYPERV
Site : NewBerlinSite
PS C:\> Get-ADDomainController -Discover -ForceDiscover
Domain : NWTraders.Com
Forest : NWTraders.Com
HostName : {HyperV.NWTraders.Com}
IPv4Address : 192.168.1.100
IPv6Address :
Name : HYPERV
Site : NewBerlinSite
PS C:\>

When using the Get-ADDomainController cmdlet, a minimal amount of information is returned. If you wish to see additional information from the domain controller you discovered, you will need to connect to it by using the –identity parameter. The identity can be an IP address, GUID, host name, or even a NetBIOS sort of name. This is shown here:

 

PS C:\> Get-ADDomainController -Identity hyperv
ComputerObjectDN : CN=HYPERV,OU=Domain Controllers,DC=NWTraders,DC=Com
DefaultPartition : DC=NWTraders,DC=Com
Domain : NWTraders.Com
Enabled : True
Forest : NWTraders.Com
HostName : HyperV.NWTraders.Com
InvocationId : 6835f51f-2c77-463f-8775-b3404f2748b2
IPv4Address : 192.168.1.100
IPv6Address :
IsGlobalCatalog : True
IsReadOnly : False
LdapPort : 389
Name : HYPERV
NTDSSettingsObjectDN : CN=NTDS Settings,CN=HYPERV,CN=Servers,CN=NewBerlinSite,
CN=Sites,CN=Configuration,DC=NWTraders,DC=Com
OperatingSystem : Windows Server 2008 R2 Standard
OperatingSystemHotfix :
OperatingSystemServicePack :
OperatingSystemVersion : 6.1 (7600)
OperationMasterRoles : {SchemaMaster, DomainNamingMaster}
Partitions : {DC=ForestDnsZones,DC=NWTraders,DC=Com, DC=DomainDnsZon
es,DC=NWTraders,DC=Com, CN=Schema,CN=Configuration,DC=N
WTraders,DC=Com, CN=Configuration,DC=NWTraders,DC=Com..
.}
ServerObjectDN : CN=HYPERV,CN=Servers,CN=NewBerlinSite,CN=Sites,CN=Confi
guration,DC=NWTraders,DC=Com
ServerObjectGuid : ab5e2830-a4d6-47f8-b2b4-25757153653c
Site : NewBerlinSite
SslPort : 636
PS C:\>

As seen in the output above, the server named Hyperv is a Global Catalog server. It also holds the SchemaMaster and the DomainNamingMaster FSMO roles. It is running Windows Server 2008 R2 Standard edition. The Get-ADDomainController cmdlet accepts a –filter parameter that can be used to perform a search-and-retrieve operation. It uses special search syntax that is discussed in the online help about files. Unfortunately, it does not accept LDAP syntax, and after more than 10 years’ experience with Active Directory and 14 years’ experience with Microsoft Exchange products, I know LDAP pretty well (not to mention email products before Microsoft Exchange was released). Therefore, I am not too inclined to learn special filter syntax just so I can use one or two cmdlets.

Luckily, I do not have to learn the special filter syntax because the Get-ADObject cmdlet will accept a LDAP dialect filter. I can simply pipe the results of the Get-ADObject cmdlet to the Get-ADDomainController cmdlet. This is shown here:

 

PS C:\> Get-ADObject -LDAPFilter "(objectclass=computer)" -searchbase "ou=domain cont
rollers,dc=nwtraders,dc=com"
| Get-ADDomainController
ComputerObjectDN : CN=HYPERV,OU=Domain Controllers,DC=NWTraders,DC=Com
DefaultPartition : DC=NWTraders,DC=Com
Domain : NWTraders.Com
Enabled : True
Forest : NWTraders.Com
HostName : HyperV.NWTraders.Com
InvocationId : 6835f51f-2c77-463f-8775-b3404f2748b2
IPv4Address : 192.168.1.100
IPv6Address :
IsGlobalCatalog : True
IsReadOnly : False
LdapPort : 389
Name : HYPERV
NTDSSettingsObjectDN : CN=NTDS Settings,CN=HYPERV,CN=Servers,CN=NewBerlinSite,
CN=Sites,CN=Configuration,DC=NWTraders,DC=Com
OperatingSystem : Windows Server 2008 R2 Standard
OperatingSystemHotfix :
OperatingSystemServicePack :
OperatingSystemVersion : 6.1 (7600)
OperationMasterRoles : {SchemaMaster, DomainNamingMaster}
Partitions : {DC=ForestDnsZones,DC=NWTraders,DC=Com, DC=DomainDnsZon
es,DC=NWTraders,DC=Com, CN=Schema,CN=Configuration,DC=N
WTraders,DC=Com, CN=Configuration,DC=NWTraders,DC=Com..
.}
ServerObjectDN : CN=HYPERV,CN=Servers,CN=NewBerlinSite,CN=Sites,CN=Confi
guration,DC=NWTraders,DC=Com
ServerObjectGuid : ab5e2830-a4d6-47f8-b2b4-25757153653c
Site : NewBerlinSite
SslPort : 636
ComputerObjectDN : CN=DC1,OU=Domain Controllers,DC=NWTraders,DC=Com
DefaultPartition : DC=NWTraders,DC=Com
Domain : NWTraders.Com
Enabled : True
Forest : NWTraders.Com
HostName : DC1.NWTraders.Com
InvocationId : fb324ced-bd3f-4977-ae69-d6763e7e029a
IPv4Address : 192.168.1.101
IPv6Address :
IsGlobalCatalog : True
IsReadOnly : False
LdapPort : 389
Name : DC1
NTDSSettingsObjectDN : CN=NTDS Settings,CN=DC1,CN=Servers,CN=NewBerlinSite,CN=
Sites,CN=Configuration,DC=NWTraders,DC=Com
OperatingSystem : Windows Serverr 2008 Standard without Hyper-V
OperatingSystemHotfix :
OperatingSystemServicePack : Service Pack 2
OperatingSystemVersion : 6.0 (6002)
OperationMasterRoles : {PDCEmulator, RIDMaster, InfrastructureMaster}
Partitions : {DC=ForestDnsZones,DC=NWTraders,DC=Com, DC=DomainDnsZon
es,DC=NWTraders,DC=Com, CN=Schema,CN=Configuration,DC=N
WTraders,DC=Com, CN=Configuration,DC=NWTraders,DC=Com..
.}
ServerObjectDN : CN=DC1,CN=Servers,CN=NewBerlinSite,CN=Sites,CN=Configur
ation,DC=NWTraders,DC=Com
ServerObjectGuid : 80885b47-5a51-4679-9922-d6f41228f211
Site : NewBerlinSite
SslPort : 636
PS C:\>

If it returns too much information (TMI), the Active Directory cmdlets work just like any other Windows PowerShell cmdlet. Use the pipeline to choose what you wish to display. MP, a nice table is seen here that contains exactly the information you requested:

 

PS C:\> Get-ADObject -LDAPFilter "(objectclass=computer)" -searchbase "ou=domain cont
rollers,dc=nwtraders,dc=com"
| Get-ADDomainController | Format-table -Property name,
operationMasterRoles -Wrap -AutoSize
name operationMasterRoles
---- --------------------
HYPERV {SchemaMaster, DomainNamingMaster}
DC1 {PDCEmulator, RIDMaster, InfrastructureMaster}
PS C:\> 

The above command is a single command that could be typed on a single line, depending on your screen resolution. In comparison, a VBScript to retrieve the FSMO role holders runs longer than 30 lines of code.

 

MP, that is all there is to using the Active Directory cmdlets to retrieve FSMO role holders from domain controllers. Active Directory Domain Services Week will continue tomorrow when we will talk about using the Active Directory cmdlets to work with user objects.

We invite you to follow us on Twitter and Facebook. If you have any questions, send email to us at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys