When you use the Microsoft Management Console (MMC) Active Directory Users and Computers snap-in to create a new user in Active Directory (AD), the snap-in asks you to provide only the attributes necessary to create a new entry in AD. However, if you open the Properties dialog box for that user account after you've created it, you'll see a myriad of optional attributes that you can set. You can set many of those optional attributes through the properties of Active Directory Service Interfaces' (ADSI's) IADsUser interface. For example, you can use the IADs User interface's FirstName, LastName, Description, and Profile properties to set a user's first name, last name, description, and profile path, respectively. IADsUser provides a simple, convenient method for populating optional attributes for a user account in AD.
However, the AD schema has attributes that don't appear in the Properties dialog box. If you have no knowledge of these attributes, you can't manipulate them with IADsUser interface properties. To further complicate matters, administrators can extend the AD schema to include custom attributes. In other words, if the administrators want to create a new attribute called MothersMaidenName to support a proprietary application, they can do so by extending the AD schema to include this custom attribute. If administrators can extend the schema, ADSI can't possibly map every attribute in the namespace to an interface property. (Not even every built-in attribute has a built-in interface; in such cases, you use the IADs interface's Get and Put methods to retrieve and set the value.) Thus, MothersMaidenName won't appear in the Properties dialog box or in Microsoft Visual Basic's (VB's) object browser when you view the IADsUser interface.
Fortunately, you can use the IADs interface's Schema property to query an AD object's schema and receive a list of all available mandatory and optional properties (including custom properties) for an object class. To see which of those properties are already populated (i.e., have values set for them), you can use the IADsPropertyList interface. This interface returns not only the names but also the values of the populated properties.
Examining All Available Attributes
By enumerating the collection that the IADs interface's Schema property returns, you can display the mandatory and optional properties of any object in the LDAP: namespace. For example, you can use the code in Listing 1 to display the mandatory properties of a User object. First, the code binds to a User object. In this case, the code binds to the User object that represents Joe Bloggs, but you can bind to any User object in AD. The properties returned will be the same because the object's class (in this case, User), not the individual object, determines the available properties.
Next, the code queries the IADs interface's Schema property and enu-merates the resulting collection to derive a list of mandatory properties. If you want to list the optional properties, you simply change the code
For Each Property In _ SchemaObj.MandatoryProperties
For Each Property In _ SchemaObj.OptionalProperties
If you want to display the mandatory properties of a Group object, you simply change the code that callout A in Listing 1 highlights with the code in Listing 2. By adapting the code, you can view a complete list of properties for any given object class. (For information about adapting the code in Listing 1 and the other listings, see the sidebar "Code Use with Objects Outside AD," page 16.)
Exploiting the Property Cache to Display Only Populated Properties
If you want to see only the populated properties for an object, you can use the IADsPropertyList interface. Unlike the IADs interface's Schema property, which retrieves properties from AD, the IADsPropertyList interface retrieves properties from the property cache. The property cache contains only populated properties and their values for objects in AD. (For more information about the property cache, see the Web-exclusive sidebar "The Core of ADSI's Efficiency: The Property Cache," http://www.winscriptingsolutions.com, InstantDoc ID 23065.)
Capitalizing on the fact that the property cache contains only populated properties, you can create a list of all property values without knowing a single property name for an object. You simply enumerate the entire property cache and display all the populated properties. This technique is useful when you don't want to display all available attributes or hard-code property names when querying an object's property values.
Using the code that Listing 3 shows, you can display the properties currently in the property cache for a given ADsPath (i.e., a reference to an object through a namespace). Because each object in AD has a unique ADs-Path, the code in Listing 3 returns the populated properties of an individual object—in this case, the populated properties for the User object that represents Joe Bloggs. If you want to display the populated properties of a different object, you simply change the ADsPath in the code that callout A in Listing 3 highlights.
Some Help from Redmond
The IADs interface's Schema property and the IADsPropertyList interface provide the names of properties. Knowing a property's name gives you a start to programmatic manipulation, but you still need to know the property's data type and whether the property is read/write or read-only. Although determining the data types for some properties is easy (e.g., LastName property, whose data type is string), determining the data types for other properties is difficult (e.g., LogonHours property, whose data type is octetstring).
Thankfully, Microsoft has come to the rescue by providing VB code that you can use to learn about the property values in the property cache. To download this property cache code, go to http://msdn.microsoft.com/msdnfiles/026/001/158/propertylist_vb_dnld.exe. If you don't have VB, I've modified and compiled Microsoft's property cache code into a COM object called property cache.dll, which you can download from the Code Library on the Windows Scripting Solutions Web site (http:// www.winscriptingsolutions.com). You can use propertycache.dll with any COM automation scripting language, including VBScript, JScript, and Perl.
If you need the source code for propertycache.dll, you'll need to recreate it because copyright agreements prevent publication of the source code directly on the Windows Scripting Solutions Web site. To recreate the source code that the compiled COM object propertycache.dll uses, follow these steps:
- Download Microsoft's property cache code and run the self-extracting executable to unpack the files into a directory.
- Download class1modulecode.txt from the Code Library.
- Open VB, create a new ActiveX DLL project, and add adshelper.bas from the Microsoft code to your project.
- Copy the code in the class1modulecode .txt file and paste it into the Class1 class module.
- Rename the project PropertyCache and rename the Class1 class module Functions (i.e., PropertyCache.Functions).
- Add a reference to Active DS Type Library and ADsSecurity 2.5 Type Library.
To use propertycache.dll, you first need to register it with the Regsvr32 utility. Then, you can use the Windows Script Host (WSH) code in Listing 4, page 15, to create a command-line query tool. Because the PropertyCache.Functions code is a COM object, you can just as easily implement it within an Active Server Pages (ASP) file or Visual Basic for Applications (VBA) macro.
Continuing the AD advanced topics theme, I'll begin a multipart series about the Windows 2000 Support Tools in the iadstools.dll library in my next column. I'll demonstrate how you can leverage this powerful API to programmatically administer AD, including managing Group Policies and triggering and monitoring AD replication.