Making use of ActiveDirectory

This article was originally published in VSJ, which is now part of Developer Fusion.
The new System.DirectoryServices.ActiveDirectory namespace published in the .NET Framework 2.0 offers exciting possibilities for administrators of Windows 2003 server based systems. The namespace makes it possible to write custom applications to retrieve information and manage your Active Directory infrastructure components. This article discusses some classes that can be used to perform common system administration tasks.

All references and code samples in this article are based on the Beta version of the .NET Framework released with Visual Studio 2005 Beta 1, and could be changed when the final version is released.

Introduction

In previous versions of the .NET framework, the interaction with Active Directory has been limited to functionality found in the System.DirectoryServices namespace. System.DirectoryServices made it possible to bind to objects in Active Directory and retrieve or change attribute values for the object.

In the beta version of the .NET framework 2.0, an additional namespace has been added called ActiveDirectory, that includes all functionality required to manage Active Directory infrastructure components such as:

  • Forests
  • Domains
  • Domain Controllers
  • Sites
  • Replication
The addition of this namespace will make managed code even more attractive to use for system administration, as a replacement for scripting technologies like VB script.

Class mapping

The key classes in the ActiveDirectory namespace are directly related to the hierarchy that an Active Directory infrastructure is made of. Figure 1 shows how classes in the namespace are mapped to components in the Active Directory hierarchy starting at the forest level.

Figure 1
Figure 1: The important classes in the ActiveDirectory namespace

Enumerating Active Directory Information

To retrieve information about your Active Directory infrastructure, you can start from the top and retrieve a Forest object to determine the Active Directory forest in which the domain that the executing computer is located.

This function returns a Forest object that can in turn be used to retrieve further information about Domains in the Active Directory Forest.

Private Function _
	Getforest() _
	As Forest
	Dim myForest _
		As Forest
	myForest = _
		Forest.Current
	Return myForest
End Function
Using the forest object, a collection of domains can be retrieved using the function below.
Private Function GetDomains() _
	As DomainCollection
	Dim myDomains As DomainCollection
	myDomains = Getforest.Domains
	Return myDomains
End Function
To continue the enumeration, each domain object in the DomainCollection is used to enumerate domain controllers in the domain. The full code below will list each domain in the forest, and all domain controllers in each enumerated domain.
Imports
System.DirectoryServices.ActiveDirectory
Module ADmod
	Public Sub Main()
		Dim myDomain As Domain
		Dim myDC As DomainController
		For Each myDomain In _
			GetDomains()
			Console.WriteLine( _
				“=====================”)
			Console.WriteLine( _
			“Domain Controllers in “ & _
				myDomain.Name)
			Console.WriteLine(“”)
			For Each myDC In _
			myDomain.DomainControllers
				Console.WriteLine( _
					myDC.Name)
			Next
		Next
	End Sub
	Private Function Getforest() _
		As Forest
		Dim myForest As Forest
		myForest = Forest.Current
		Return myForest
	End Function
	Private Function GetDomains() _
		As DomainCollection
		Dim myDomains As _
			DomainCollection
		myDomains = Getforest.Domains
		Return myDomains
	End Function
End Module

Managing FSMO Roles

There are two different ways to discover information about FSMO roles in your Forest and Domains. You can bind to a specific domain controller and query it for a collection of roles currently held (if any), or you can query a Domain or Forest object specifically about which Domain Controller each role is hosted on.

This snippet will bind to a domain controller and enumerate roles in the ActiveDirectoryRoles collection. Notice the DirectoryContext.Open method is used to instantiate the DomainController object when it is not retrieved from a Domain object.

Private Sub EnumDCRoles(DCName _
	As String)
	Dim myDC As DomainController
	Dim myRole As ActiveDirectoryRole
	myDC =DomainController.GetObject( _
		DirectoryContext.Open(DCName)
	For Each myRole In myDC.Roles
		Console.WriteLine( _
			myRole.ToString)
	Next
End Sub
To retrieve FSMO information from a Domain or Forest, you need to specifically query for each role individually. This snippet binds to a domain and lists the server names that hold each domain wide FSMO role.
Private Sub EnumDomainRoles( _
	DomainName as String)
	Dim myDomain As Domain
	myDomain Domain.GetObject( _
		DirectoryContext.open( _
		DomainName))
	Console.WriteLine( _
		“Operation master roles in “ &_
		 DomainName)
	Console.WriteLine(“”)
	Console.WriteLine( _
		“PDC Emulator: “ & _
		myDomain.PdcRoleOwner.Name)
	Console.WriteLine( _
		“Infrastructure Manager: “ & _
myDomain.InfrastructureRoleOwner.Name)
	Console.WriteLine(“Rid Master: “ &_
		myDomain.RidRoleOwner.Name)
End Sub

Transferring FSMO Roles

FSMO roles can be either seized or relocated to another server. The difference between seizing a role and transferring it is that when transferring a role, the domain controller that currently holds the role is still online. The methods of the DomainController object available for these operations are SeizeRoleOwnership and TransferRoleOwnership. Both methods require Integers as an input parameter that are defined in the ActiveDirectoryRole enumeration, as detailed in Table 1.

Table 1

System.DirectoryServices.ActiveDirectory.ActiveDirectoryRole
SchemaRole 0
NamingRole 1
PdcRole 2
RidRole 3
InfrastructureRole 4

Consider the following snippet to transfer roles to an alternative Domain Controller:

Private Sub TransferRole(
	ByVal RoleToTransfer As _
	ActiveDirectoryRole, _
	ByVal DCTargetName As String)
	Dim myDC As DomainController
	myDC = DomainController.GetObject(_
		DirectoryContext.Open( _
		DCTargetName))
	myDC.TransferRoleOwnership( _
		RoleToTransfer)
End Sub

Managing Active Directory Sites and Subnets – Retrieving Site and Subnet information

The namespace contains a full set of classes that can be used to manage forest-wide components such as Sites, Subnets and Site Links that are used to define replication boundaries. Since Sites are Fforest-wide, all sites can be enumerated by retrieving a collection of site objects from the Forest.Sites property. Each Site object in turn has a Subnets property that contains a collection of subnets that are assigned to a site. This code snippet will list all sites in a Forest and display what subnets are assigned to each site.
Private Sub ListSites()
	Dim myForest As Forest
	Dim mySites As _
		ReadOnlySiteCollection
	Dim mySubnets As _
		ActiveDirectorySubnetCollection
	Dim iEnumSites, iEnumSubnets _
		As Integer
	myForest = Forest.Current
	mySites = myForest.Sites
	For iEnumSites = 0 To _
		mySites.Count -1
		Console.WriteLine(mySites( _
			iEnumSites).Name)
		Console.WriteLine( _
			“***Assigned Subnets***”)
		mySubnets = _
			mySites(iEnumSites).Subnets
		For iEnumSubnets = 0 To_
			mySubnets.Count – 1
			Console.WriteLine( _
				mySubnets( _
				iEnumSubnets).Name)
		Next
	Next
End Sub

Creating new Sites and Subnets

A new Site is created by instantiating a new ActiveDirectorySite object. The constructor requires the DirectoryContext as a parameter to determine the Forest in which to create the site and the credentials to use to access Active Directory. By default the current domain and the logged-on user’s credentials are used. A string value is also required for the name of the new site. After the object has been instantiated, options can be configured and Subnets assigned to the Site. To complete the operation the save method must be called to commit the changes.
Private Sub CreateSite( _
	ByVal Sitename as String)
	Dim mySite As ActiveDirectorySite
	mySite = New ActiveDirectorySite( _
		DirectoryContext.Open(), _
		“MyNewSite”)
	mySite.Options = _
		ActiveDirectorySiteOptions. _
		TopologyCleanupDisabled
	mySite.Save()
End sub
Subnets are created in a similar way to sites. One difference is that the Subnet constructor contains an overloaded method which gives an option to assign the subnet to a site upon creation.
Dim mySubnet = _
	New ActiveDirectorySubnet( _
	DirectoryContext.Open(), _
	“192.168.1.0/24”, “MyNewSite”)

Managing Replication

Extensive possibilities are available to manage replication of Active Directory partitions, such as:
  • Retrieving information about pending operations
  • Initiate replication from a replication neighbor, any specific Domain Controller, or all Domain Controllers
  • Retrieving information about the replication topology
Initiating replication from code could be very useful if an application modifies an object in Active Directory, and the changes need to be replicated before other procedures in the application are called. The classes available also provide the opportunity to develop customized tools for troubleshooting Active Directory replication.

This example shows how replication of the configuration partition is initiated:

Private Sub replicate(_
	ByVal SourceDC As String, _
		ByVal DestDC As String)
	Dim myDC As DomainController
	myDC = DomainController.GetObject(_
	DirectoryContext.Open(SourceDC))
	myDC.SyncReplicaFromServer( _
“CN=Configuration,DC=Fabrikam,DC=Com”,_
	DestDC)
End Sub

Conclusion

The managed code interface to Active Directory that is provided by the classes in the ActiveDirectory namespace extend the opportunity to use the .NET Framework for system administration. Information about the Active Directory infrastructure can now be retrieved and used where required in applications without the use of unmanaged code, and customised applications for administration and troubleshooting of Active Directory can now be developed.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“It works on my machine.” - Anonymous