[ Team LiB ] |
19.1 The IADs PropertiesThe IADs properties are as follows:
Each of these properties has a corresponding property method in the IADs interface. You can use the property method, which has the same name as the property, to access that property's value. Example 19-1 contains code to display the six IADs properties for a user object. Example 19-1. Using the explicit property methods to display the six IADs propertiesDim objUser 'An ADSI User object Dim str 'A text string ` User object using the WinNT namespace Set objUser=GetObject("WinNT://MYCORP/Administrator,User") str = "Name: " & objUser.Name & vbCrLf str = str & "GUID: " & objUser.GUID & vbCrLf str = str & "Class: " & objUser.Class & vbCrLf str = str & "ADsPath: " & objUser.ADsPath & vbCrLf str = str & "Parent: " & objUser.Parent & vbCrLf str = str & "Schema: " & objUser.Schema & vbCrLf & vbCrLf Set objUser = Nothing ` User object using the LDAP namespace Set objUser=GetObject("LDAP://cn=Administrator,cn=Users,dc=mycorp,dc=com") Str = str & "Name: " & objUser.Name & vbCrLf Str = str & "GUID: " & objUser.GUID & vbCrLf Str = str & "Class: " & objUser.Class & vbCrLf Str = str & "ADsPath: " & objUser.ADsPath & vbCrLf Str = str & "Parent: " & objUser.Parent & vbCrLf str = str & "Schema: " & objUser.Schema & vbCrLf & vbCrLf WScript.Echo str Set objUser = Nothing To begin, we declare two variables (i.e., str and objUser), invoke the GetObject method to create a reference to the user object, and assign it to objUser. We then set the str variable to the string "Name:" and apply the IADs::Name property method (i.e., objUser.Name) to retrieve the Name property's value (i.e., Administrator). The carriage-return line-feed constant (vbCrLf) specifies to move to the start of a new line. At this point, str represents the string "Name: Administrator." In the next line, we use the IADs::GUID property method (objUser.GUID) to retrieve the GUID property's value (i.e., {D83F1060-1E71-11CF-B1F3-02608C9E7553}). We are appending the GUID to previous value set in str so the new str represents the Name property value and the GUID property value. This was repeated until all six core properties in both the WinNT and the LDAP namespaces were retrieved. You might be surprised to find out that enumerating properties in different namespaces produces different output, as Figure 19-1 shows. For example, the Name property under the LDAP namespace has "cn=" included, whereas the Name property under the WinNT namespace doesn't. Figure 19-1. The IADs properties from the WinNT and LDAP namespacesBoth the code and the figure demonstrate another important point: The type of directory can affect the results. For example, using the IADs::Parent property makes sense when you're using the LDAP namespace to access a hierarchical directory such as Active Directory, because you can see parent-child relationships (e.g., you can see that the Users container is the parent for the Administrator User object). However, using the IADs::Parent property to look at NT's Security Accounts Manager (SAM) doesn't make sense where domains are concerned because the contents are all in one flat namespace. 19.1.1 Using IADs::Get and IADs::PutWhile you can use property methods to access an object's properties, you can also use the IADs interface's IADs::Get and IADs::Put methods to retrieve any attribute on the object. In other words, the following two sets of statements are equivalent: strName = objUser.description objUser.description = strName strName = objUser.Get("description") objUser.Put "description", strName However, using the IADs::Get and IADs::Put methods is more of a performance hit as it involves internally doing a search for the property specified. Compared to this, the direct use of a property is what is known as a direct vtable binding per the COM documentation and is the faster of the two. IADs::Get and IADs::Put should be used only when a generic browser or program is written to work with any ADSI object. See Table 19-1 for the full set of methods and property methods for the IADs interface.
For example, the next script shows how you use IADs::Get and IADs::Put to retrieve, change, and return the mail property. After we set the objGroup variable to the pointer to the Managers group, we use the IADs::Get method (objGroup.Get) with the "mail" argument to retrieve the mail property's value. The WScript.Echo method displays the results in a window. Changing the value and returning it to the property cache is just as simple. You use the IADs::Put method with the argument "mail". You don't put the argument in parentheses when you use the IADs::Put method: the method in a subprocedure, not a function, and it doesn't return a value. The string that follows the IADs::Put function contains the Managers group's new mail contact address. To write the new mail property to Active Directory, you use IADs::SetInfo: Set objGroup = GetObject("LDAP://cn=Managers,ou=Sales,dc=mycorp,dc=com") WScript.Echo objGroup.Get("mail") objGroup.Put "mail", "[email protected]" objGroup.SetInfo 19.1.2 The Property CacheHaving looked at properties and property methods, let's take a look at the property cache, a location in memory on the local machine running the script that stores properties for objects. Each object that you bind to has a personal property cache; the OS creates this cache the instant the bind succeeds. However, the OS doesn't immediately populate the cache with values. When you use the IADs::Get method to retrieve an object's property, ADSI doesn't go to Active Directory to retrieve the value. Instead, ADSI reads the value from the property cache on the client executing the script. If ADSI doesn't find the property in the property cache when the call comes in, the system implicitly executes an IADs::GetInfo call to read all the properties for the current object into the cache. (You also can explicitly use the IADs::GetInfo method to populate the property cache with an object's properties.) The IADs::Get method then reads the appropriate value from the newly created cache. Microsoft designed the property cache with efficiency in mind. The property cache lets you access an object's properties with a minimum number of calls, thereby minimizing network traffic. Retrieving all of an object's properties with one IADs::GetInfo call is more efficient than individually retrieving each property. Similarly, the process of writing all of an object's properties first to the cache and then to Active Directory with one IADs::SetInfo call is more efficient than writing each property individually to Active Directory. 19.1.3 Be CarefulThe IADs::GetInfo and IADs::SetInfo methods are two of the most important methods you'll use. However, you need to be aware of two possible problems. The first problem can arise if you try to access a property that doesn't have a value. For example, when you create a group object, the mail property doesn't automatically receive a value; you must provide a value, such as [email protected]. When you use the IADs::GetInfo method, only those properties that have values appear in the property cache. Thus, if you don't give the mail property a value and you use IADs::GetInfo, the mail property value won't be in the property cache. If you try to access a property that doesn't exist in the cache, the script will give an empty value as the result.
Another problem can arise if you forget to use IADs::SetInfo after modifying a property. For example, suppose you want to change the Managers group's mail property value and you create the script shown in Example 19-2. Example 19-2. Making the mistake of forgetting the SetInfo callDim objGroup 'An ADSI group object Set objGroup = GetObject("LDAP://cn=Managers,ou=Sales,dc=mycorp,dc=com") '********************************************************************** 'Get and write the mail property value, which forces an 'implicit GetInfo call '********************************************************************** WScript.Echo objGroup.Get("mail") '********************************************************************** 'Set the new mail address in the cache '********************************************************************** objGroup.Put "mail", "[email protected]" '********************************************************************** 'Use an explicit GetInfo call to again retrieve all items into the cache '********************************************************************** objGroup.GetInfo WScript.Echo objGroup.mail In Example 19-2, we set the objGroup variable to the pointer to the Managers group. To display the current mail property value in a window, we use the WScript::Echo method with the IADs::Get method, which forces an implicit IADs::GetInfo call. We then set the new value for the objGroup's mail property, after which we use an explicit IADs::GetInfo call to again retrieve all the object's properties into the cache. Finally, we use the WScript.Echo method to display the results in a window. When you run the script, two windows pop up. To your dismay, both windows state the original value of the mail property, which means that the system didn't write the new mail address to Active Directory. This cache write didn't occur because you need to explicitly call the IADs::SetInfo method to write out data from the cache to Active Directory. To fix the script, you need to insert the line: objGroup.SetInfo between the line setting the new mail address and the line making the explicit IADs::GetInfo call. 19.1.4 More Complexities of Property Access: IADs::GetEx and IADs::PutExUsing the IADs interface's IADs::Get method works well for properties with one value. However, some properties have multiple values, such as a user with several telephone numbers. If a property stores multiple values, you need to use the IADs interface's IADs::GetEx[2] and IADs::PutEx methods to retrieve and return the values.
19.1.4.1 Using IADs::GetExThe following script shows how to use IADs::GetEx. In this script, we pass the multiple-value property as an argument to the IADs::GetEx method. We then use a For Each...Next loop on the resulting list. Dim objUser 'An ADSI user object Dim arrPhoneList 'An array of phone numbers Dim strPhoneNumber 'An individual phone number Set objUser=GetObject("LDAP://cn=administrator,cn=Users,dc=mycorp,dc=com") arrPhoneList = objUser.GetEx("telephoneNumber") For Each strPhoneNumber In arrPhoneList WScript.Echo strPhoneNumber Next When we make the IADs::GetEx call, the system makes an implicit IADs::GetInfoEx call rather than an implicit IADs::GetInfo call to Active Directory. You can use an explicit IADs::GetInfoEx call to get one or more properties if you don't want to use IADs::GetInfo to get all the property values. However, few scriptwriters use IADs::GetInfoEx for this purpose, because they typically use implicit calls or use IADs::GetInfo to read all values into the property cache. In addition, if you use IADs::GetEx for every property retrieval rather than using IADs::GetInfo, your underlying network traffic will increase. Instead of sending one request to the server for all the information, you'll be sending several requests for smaller amounts of information. Although IADs::GetInfoEx isn't a good substitute for IADs::GetInfo, it works well for selectively reading properties into the property cache. Example 19-3 shows how to selectively retrieve only two properties. Example 19-3. Selectively reading properties into the property cache using the GetInfo methodDim objUser 'An ADSI user object Dim arrProps 'An array of properties to return Set objUser=GetObject("LDAP://cn=administrator,cn=Users,dc=mycorp,dc=com") '********************************************************************** 'Set the list of properties to return '********************************************************************** ArrProps = Array("cn","ADsPath") '********************************************************************** 'Get the specified properties '********************************************************************** objUser.GetInfoEx arrProps, 0 WScript.Echo objUser.cn & vbTab & objUser.ADsPath After we set the objUser variable, we create an array containing the properties we want (i.e., cn and ADsPath). Next, we pass that array to the IADs::GetInfoEx method as the first parameter. (The second parameter must be 0 for all actions; however, it is reserved and could be used in a later version of ADSI.) Then, the last line uses the WScript.Echo method to print the cn and ADsPath attributes, separating them with a tab. 19.1.4.2 Using IADs::PutExTo set multivalue properties, you use the IADs::PutEx method. This is slightly more complicated than using IADs::GetEx. Suppose a property already has three values (e.g., pager numbers), and you want to put in two more. You must let IADs::PutEx know whether it needs to overwrite, update, or add to the existing values. You use the constants in Table 19-2 to tell IADs::PutEx what to do.
Use the constant name only if you're using VB. If you use VBScript with the WSH, you must either define the constants, as we've done in Example 19-4, or use the values directly. The four values are fairly straightforward to use, as the example script shows. Example 19-4. Using constants with the PutEx method to update the property cacheConst ADS_PROPERTY_CLEAR = 1 Const ADS_PROPERTY_UPDATE = 2 Const ADS_PROPERTY_APPEND = 3 Const ADS_PROPERTY_DELETE = 4 Dim objUser 'An ADSI User object Dim strPager 'A text string holding a phone number Set objUser=GetObject("LDAP://cn=Administrator,cn=Users,dc=mycorp,dc=com") '********************************************************************** 'Set three telephone numbers for the Administrator account '********************************************************************** objUser.PutEx ADS_PROPERTY_UPDATE, "pager", _ Array("123-1234", "234-2345", "345-3456") objUser.SetInfo objUser.GetInfo For Each strPager in objUser.telephoneNumber WScript.Echo strPager Next '********************************************************************** 'Delete the first and last number '********************************************************************** objUser.PutEx ADS_PROPERTY_DELETE, "pager", Array("123-1234", "345-3456") objUser.SetInfo objUser.GetInfo For Each strPager in objUser.telephoneNumber WScript.Echo strPager Next '********************************************************************** 'Add a new telephone number without deleting the remaining number '********************************************************************** objUser.PutEx ADS_PROPERTY_APPEND, "pager", Array("456-4567") objUser.SetInfo objUser.GetInfo For Each strPager in objUser.telephoneNumber WScript.Echo strPager Next '********************************************************************** 'Delete all values '********************************************************************** objUser.PutEx ADS_PROPERTY_CLEAR, "pager", vbNull objUser.SetInfo objUser.GetInfo For Each strPager in objUser.telephoneNumber WScript.Echo strPager Next After binding to the user object, three pager numbers are set for the Administrator account, wiping out any existing values. The property cache is then reloaded explicitly to make sure it contains the new values that were just set. Now, a For Each loop is used to go through the newly set property to show the individual pager numbers. The first and last pager numbers of the new property are deleted in the cache and written to Active Directory with SetInfo. At this point, Active Directory should contain only one pager number, which is displayed by looping through the values again. Next we append a number to the value held for that property in the cache and subsequently write it out to Active Directory, leaving two numbers in Active Directory for that property. Looping through the values again shows there are two numbers. Finally, all values in the property cache for that property are deleted, and the changes are updated in Active Directory. Using the For Each loop one last time should show no values. Knowing now that you can access all of an object's properties from the cache individually, it would make sense if there were a way to count the number of items, display their names as well as their values, and so on. For this purpose, Microsoft provided three interfaces: IADsPropertyList, IADsPropertyEntry, and IADsPropertyValue. |
[ Team LiB ] |