[ Team LiB ] |
19.2 Manipulating the Property CacheThere will be times when you need to write a script that queries all the values that have been set in the underlying directory for a particular object. For example, suppose you're one of several systems administrators who work with your company's Active Directory implementation. You need to write a script that queries all the property values that the administrators have set for a particular user. Discovering the set property values for an object can be a long, tedious job. Fortunately, ADSI provides a quick method. If someone has set a value for a property, it must be in that object's property cache. So all you need to do is walk through the property cache, displaying and optionally modifying each item as you go. In this section, we'll describe the property cache mechanics and show you how to write scripts that use several ADSI methods and properties to add individual values, add a set of values, walk through the property cache, and write modifications to the cache and to the directory. Although these examples access the Lightweight Directory Access Protocol (LDAP) namespace, you can just as easily substitute the WinNT namespace in any of the scripts and run them against Windows NT servers. Details of the property cache interfaces can be found at the MSDN Library (http://msdn.microsoft.com/library/) by clicking through the following links: Networking and Directory Services Active Directory, ADSI, Directory Services SDK Documentation Directory Services Active Directory Service Interfaces Active Directory Service Interfaces Reference ADSI Interfaces Property Cache Interfaces. 19.2.1 Property Cache MechanicsEvery object has properties. When you perform an explicit IADs::GetInfo call (or an implicit IADs::GetInfo call using IADs::Get) on an object that you previously bound to, the OS loads all the properties for that specific object into that object's property cache. Consider the property cache a simple list of properties. The PropertyList object represents this list. You can use several IADsPropertyList methods to navigate through the list and access items. For example, you can navigate the list and access each item, every nth item, or one particular item based on its name. Each item in the property list is a property entry represented by the PropertyEntry object. You use the IADsPropertyEntry interface to access property entries. A property entry can have one or more property values. To access values in a property entry, you use the IADsPropertyValue interface. To summarize, use IADsPropertyList to navigate through and access property entries in the property list. When you want to manipulate a property, use IADsPropertyEntry. To access the values of that property entry, use IADsPropertyValue. 19.2.2 Adding Individual ValuesTo show you how to add an individual value, we'll expand on one of the examples from the previous section: the pager property of the User object. The pager property is an array of text strings representing multiple pager numbers. Consider that any property represents data. Data can take several forms, including a string, an integer, or a Boolean value. In the cache, each property has two attributes: one attribute specifies the type of data the property represents, and the other attribute specifies the value of that data type. For example, each pager property has two attributes: a Unicode string (the type of data) and the pager number (the value of that Unicode string). The User object's lastLogon property, which specifies the time the user last logged on, has the two attributes, a LargeInteger (type of data) and a date/time stamp (the value of that LargeInteger). The pager and lastLogon properties are instances of the PropertyValue object, so you manipulate them with the method and property methods of the IADsPropertyValue interface. For example, you use the IADsPropertyValue::ADsType property method to set the PropertyValue's type of data. Table 19-3 shows some of the corresponding constant names and values that you can set for the IADsPropertyValue::ADsType property.
Suppose you want to add a PropertyValue object with the value of "Hi There!" The two attributes are a case-sensitive string (i.e., the type of data, or IADsPropertyValue::ADsType property) and "Hi There!" (i.e., the value of that case-sensitive string or the IADsPropertyValue::CaseExactString property). The constant for the IADsPropertyValue::ADsType of a case-sensitive string is ADSTYPE_CASE_EXACT_STRING, which has a numeric value of 2. As shown in Table 19-3, IADsPropertyValue::CaseExactString is one of a number of IADsPropertyValue property methods that exist, each relating to a specific data type. It is the value in IADsPropertyValue::ADsType that determines which of the many property methods are actually used to get and set the data. The following script shows how to create this new PropertyValue object. We begin by setting the ADSTYPE_CASE_EXACT_STRING constant to its numeric value (i.e., 2) and declaring the objPropValue variable. As we mentioned earlier, if you use VBScript with WSH, you must either define the constants, as the script does, or use the values directly: Const ADSTYPE_CASE_EXACT_STRING = 2 Dim objPropValue 'An ADSI PropertyValue object Set objPropValue = CreateObject("PropertyValue") objPropValue.ADsType = ADSTYPE_CASE_EXACT_STRING objPropValue.CaseExactString = "Hi There!" We use VBScript's CreateObject method to create an instance of the PropertyValue object and set it to the objPropValue variable. Then two attributes are assigned to the PropertyValue object. The objPropValue's IADsPropertyValue::ADsType property method is used to assign the property's data type to the ADSTYPE_CASE_EXACT_STRING constant. Finally, we use objPropValue's IADsPropertyValue::CaseExactString property method to assign the property's value to "Hi There!" 19.2.3 Adding Sets of ValuesAs we mentioned previously, some properties hold one value (e.g., the lastLogon property); others hold multiple values in an array (e.g., the pager property). The PropertyEntry object holds the entire set of values for a property, be it one value or many values. However, the PropertyEntry object does more than store values. This object's properties dictate how you can manipulate those values. The PropertyEntry object supports the IADsPropertyEntry interface that has four property methods:
The next script shows how to create a PropertyEntry object from one property value: Const ADSTYPE_CASE_IGNORE_STRING = 3 Const ADS_PROPERTY_UPDATE = 2 Dim objPropValue 'An ADSI PropertyValue object Dim objPropEntry 'An ADSI PropertyEntry object Set objPropValue = CreateObject("PropertyValue") objPropValue.ADsType = ADSTYPE_CASE_IGNORE_STRING objPropValue.CaseIgnoreString = "0123-456-7890" Set objPropEntry = CreateObject("PropertyEntry") objPropEntry.Name = "pager" objPropEntry.Values = Array(objPropValue) objPropEntry.ADsType = ADSTYPE_CASE_IGNORE_STRING objPropEntry.ControlCode = ADS_PROPERTY_UPDATE The first part of the script is similar to the previous one. We begin by setting the constants to their numeric values and declaring the variables. Next, we create an instance of the PropertyValue object and set it to the objPropValue variable. We then use the IADsPropertyValue::ADsType property method to assign the property's data type to the ADSTYPE_CASE_IGNORE_STRING constant and the IADsPropertyValue::CaseIgnoreString property method to assign the property's value to 0123-456-7890. The second part of the script begins by creating an instance of the PropertyEntry object and setting it to the objPropEntry variable. Then all four PropertyEntry properties are set. For the IADsPropertyEntry::Values property, you must use the VBScript Array( ) function to force the values into an array, even if you set only one value. For the IADsPropertyEntry::ControlCode property, you're replacing the existing values with the ones you're passing in. 19.2.4 Walking Through the Property CacheFor any object, the property cache consists of PropertyEntry objects that correspond to each property. When you use the IADs::Get method, it reads the cache's PropertyEntry for that particular property. As we've previously mentioned, whenever you call GetObject or IADsOpenDSObject::OpenDSObject, as explained later, the object that is returned can use the IADs interface in addition to any interface designed for that object. The IADsPropertyList interface also is directly available for any object. It is of no real use without a call to GetInfo first, without which the property cache will be empty. Once the cache is populated, however, the methods and properties come into their own. Table 19-5 lists the IADsPropertyList methods and properties.
The PropertyList object represents the entire set of properties for an object. The methods and property methods of the IADsPropertyList interface can be used to manipulate the PropertyList object. Example 19-5 uses several of those methods and property methods to demonstrate three ways of walking through the property cache. Example 19-5. Walking through the property cache with the IADsPropertyList interfaceOption Explicit '********************************************************************** 'Force error checking within the code using the Err.Number property 'method in approaches 2 and 3 '********************************************************************** On Error Resume Next '********************************************************************** 'Declare the variables '********************************************************************** Dim objGroup 'The group whose property list you want to investigate Dim strText 'A text string that displays results in one message box Dim intPropCount 'The number of properties Dim intIndex 'The index used while looping through the property list Dim objPropEntry 'An individual property entry used in a loop Set objGroup = GetObject("LDAP://cn=Managers,ou=Sales,dc=mycorp,dc=com") objGroup.GetInfo intPropCount = objGroup.PropertyCount WScript.Echo "There are " & intPropCount & " values in the property cache." '********************************************************************** 'Approach 1: PropertyCount property method '********************************************************************** strText = "" For intIndex = 0 To (intPropCount-1) strText = strText & objGroup.Item(intIndex).Name & vbTab _ & objGroup.Item(intIndex).ADsType & vbCrLf Next WScript.Echo strText '********************************************************************** 'Approach 2: Next method '********************************************************************** strText = "" Set objPropEntry = objGroup.Next While (Not (IsNull(objPropEntry)) And Err.Number = 0) strText = strText & objPropEntry.Name & vbTab & objPropEntry.ADsType & vbCrLf Set objPropEntry = objGroup.Next Wend WScript.Echo strText Set objPropEntry = Nothing '********************************************************************** 'Approach 3: Next and Skip methods '********************************************************************** strText = "" objGroup.Reset Set objPropEntry = objGroup.Next While (Not (IsNull(objPropEntry)) And Err.Number = 0) strText = strText & objPropEntry.Name & vbTab & objPropEntry.ADsType & vbCrLf objGroup.Skip(2) Set objPropEntry = objGroup.Next Wend WScript.Echo strText Set objPropEntry = Nothing The script begins by using VBScript's Option Explicit statement (which requires you to declare all variables before using them) and the On Error Resume Next statement (which allows you to do error handling). Then, after declaring the variables, the GetObject method is used to bind to the group whose property cache we want to look at. In this case, we want to view the properties for the Manager group object. Next, the IADs::GetInfo method is called to load the property cache for this group. Since we won't be using the IADs::Get method in the script, the system won't implicitly use the IADs::GetInfo method to load the cache, so we have to explicitly load it in. Each object in objGroup has a PropertyList object, so we use the IADsPropertyList::PropertyCount property method to count each PropertyList object. We store the count for later use by setting it to the intPropCount variable, and we print it out in a message box using WSH's Echo method. We now know how many properties objGroup has, but we need to find out the values of those properties. We can use one of three approaches to walk through the property cache to get this information. 19.2.4.1 Approach 1—Using the IADsPropertyList::PropertyCount property methodWe begin by walking through the property list by counting the items in the index 0 through intPropCount-1. We need to specify this index, because the property list index starts at 0 rather than 1. For example, a property list with 15 items has an index ranging from 0 to 14. For each item in the index, you concatenate (&) two property methods to retrieve the property's IADs::Name and IADsPropertyValue::ADsType. The script processes concatenated statements from left to right, so it first uses the IADsPropertyList::Item method with the intIndex value as the item number to retrieve a property entry, to which it applies the IADs::Name property method to get the property's name. The script then uses the same process to retrieve the same property entry, to which it applies the IADsPropertyValue::ADsType property method to get the property's datatype. Forcing the script to process IADsPropertyList::Item twice is inefficient. We processed it twice only to illustrate how to walk through the property list. The concatenated code includes more than just the two property methods. The code also concatenates a tab (vbTab) between the two property methods and a carriage-return line-feed (vbCrLf), or new line, after the second property method. But even more important, the code first concatenates the existing strText variable onto the front (i.e., strText = strText & property method 1 & property method 2), which means that, in the output, these property values are appended to the existing strText string. As a result, the WSH displays all the property values in one message box if you use WSH's wscript.exe scripting engine to run the script. If you're using WSH's cscript.exe scripting engine, using this append technique makes no difference. If you don't concatenate the strText variable (i.e., strText = property method 1 & property method 2), WSH displays a separate message box for each property. When the script finishes looping through the property list index, it prints the appended strText string in the message box. Approaches 2 and 3 also use the append technique to display all their output in one message box. 19.2.4.2 Approach 2—Using the IADsPropertyList::Next methodWe start this approach by resetting the strText variable to a zero-length string to ensure that no values from the previous approach are left in the string. Then the IADsPropertyList::Next method is called to retrieve a copy of the first property entry and set the result to the objPropEntry variable. Because we called the IADsPropertyList::Next method, we can use a while loop to iterate through the cache until we encounter a null value, which specifies that we're at the end of the list. Providing that the first property entry isn't a null entry, we enter the while loop. The And Err.Number = 0 code designates a test to see whether an error has occurred. A value of 0 indicates no error; any other value specifies an error. If a valid entry (i.e., not a null entry) is retrieved and an error hasn't occurred (i.e., the error number is equal to 0), we enter the loop. Within the loop, the property name and data type are appended to the strText string in a similar manner as before. To move to the next property entry in the property cache, we again call the IADsPropertyList::Next method. As long as this value isn't null and isn't generating an error code, the process continues until it hits a null entry, which means we're at the end of the list. The wend keyword signifies the end of the while loop. Finally, the results are printed. 19.2.4.3 Approach 3—Using the IADsPropertyList::Next and IADsPropertyList::Skip methodsThe code in this approach is identical to the code used in Approach 2, except for the addition of two lines. The IADsPropertyList::Reset property method sets the property list pointer to the first property entry in the cache. If we don't use the IADsPropertyList::Reset property method, the pointer will be at the end of the cache, which would generate a null entry. The IADsPropertyList::Skip code tells the IADsPropertyList::Next property method to skip the next two property entries. In other words, the IADsPropertyList::Next property method is retrieving every third property, so this approach returns only property entries 1, 4, 7, 10, and so on. 19.2.5 Writing the ModificationsNow that we've shown how to walk through the cache, next we will review how to write modifications to the cache and back to the directory. Example 19-6 illustrates these procedures. This script is an amalgam of the code in the earlier examples. As such, it shows how to assemble the pieces of code into a usable script. Example 19-6. Writing modifications to the cache and back to the directoryOption Explicit '********************************************************************** 'Force error checking within the code using the Err.Number property 'method in approaches 2 and 3 '********************************************************************** On Error Resume Next '********************************************************************** 'Declare the constants and variables '********************************************************************** Const ADSTYPE_CASE_IGNORE_STRING = 3 Const ADS_PROPERTY_UPDATE = 2 Dim objPropValue 'An ADSI PropertyValue object Dim objPropEntry 'An ADSI PropertyEntry object Dim objUser 'The user whose property list you want to investigate Dim strText 'A text string that displays results in one message box Dim intPropCount 'The number of properties Dim intIndex 'The index used while looping through the property list Set objUser = GetObject("LDAP://cn=AlistairGLN,ou=Sales,dc=mycorp,dc=com") objUser.GetInfo '********************************************************************** 'Section A: Calculate the property count, and enumerate each 'property's name and datatype '********************************************************************** intPropCount = objUser.PropertyCount WScript.Echo "There are " & intPropCount _ & " values in the property cache before adding the new one." strText = "" For intIndex = 0 To (intPropCount-1) strText = strText & objUser.Item(intIndex).Name & vbTab _ & objUser.Item(intIndex).ADsType & vbCrLf Next WScript.Echo strText '********************************************************************** 'Section B: Create a property entry, and write it to the cache '********************************************************************** Set objPropValue = CreateObject("PropertyValue") objPropValue.ADsType = ADSTYPE_CASE_IGNORE_STRING objPropValue.CaseExactString = "0123-456-7890" Set objPropEntry = CreateObject("PropertyEntry") objPropEntry.Name = "pager" objPropEntry.Values = Array(objPropValue) objPropEntry.ADsType = ADSTYPE_CASE_IGNORE_STRING objPropEntry.ControlCode = ADS_PROPERTY_UPDATE objUser.PutPropertyItem(objPropEntry) '********************************************************************** 'Section C: Write out the cache to Active Directory and read the new 'cache explicitly back in from the object '********************************************************************** objUser.SetInfo objUser.GetInfo '********************************************************************** 'Section D: Recalculate the property count, and re-enumerate each 'property's name and datatype to see the changes '********************************************************************** intPropCount = objUser.PropertyCount WScript.Echo "There are " & intPropCount _ & " values in the property cache before adding the new one." strText = "" For intIndex = 0 To (intPropCount-1) strText = strText & objUser.Item(intIndex).Name _ & vbTab & objUser.Item(intIndex).ADsType & vbCrLf Next WScript.Echo strText The script begins with Option Explicit and On Error Resume Next, after which it sets the constants, declares the variables, and sets the objUser variable to the AlistairGLN user object. The script then divides into four sections:
19.2.6 Walking the Property Cache—The SolutionExample 19-7 is quite long. It walks through the property cache for an object and prints the name, data type, and values of each entry. Some of the properties are not printable strings, so printing them in a text format makes little sense. Thus, this script prints only the text strings. We used a VBScript dictionary object to map the data type integers (ADsType) to descriptive names. A dictionary is similar in nature to an associative array or hash, which are common in other programming languages. After instantiating a dictionary object, you can use the Add method to add new key value pairs to it. The script also illustrates how you can just as easily use the WinNT namespace rather than the LDAP namespace to display properties of objects, and how you can run the script against Windows NT domains and Windows NT or later member servers rather than Active Directory. Example 19-7. Walking through the property cache of an objectOption Explicit On Error Resume Next '********************************************************************** 'Declare the hash (dictionary), constants and variables '********************************************************************** Dim dicADsType Set dicADsType = CreateObject("Scripting.Dictionary") dicADsType.Add 0, "INVALID" dicADsType.Add 1, "DN_STRING" dicADsType.Add 2, "CASE_EXACT_STRING" dicADsType.Add 3, "CASE_IGNORE_STRING" dicADsType.Add 4, "PRINTABLE_STRING" dicADsType.Add 5, "NUMERIC_STRING" dicADsType.Add 6, "BOOLEAN" dicADsType.Add 7, "INTEGER" dicADsType.Add 8, "OCTET_STRING" dicADsType.Add 9, "UTC_TIME" dicADsType.Add 10, "LARGE_INTEGER" dicADsType.Add 11, "PROV_SPECIFIC" dicADsType.Add 12, "OBJECT_CLASS" dicADsType.Add 13, "CASEIGNORE_LIST" dicADsType.Add 14, "OCTET_LIST" dicADsType.Add 15, "PATH" dicADsType.Add 16, "POSTALADDRESS" dicADsType.Add 17, "TIMESTAMP" dicADsType.Add 18, "BACKLINK" dicADsType.Add 19, "TYPEDNAME" dicADsType.Add 20, "HOLD" dicADsType.Add 21, "NETADDRESS" dicADsType.Add 22, "REPLICAPOINTER" dicADsType.Add 23, "FAXNUMBER" dicADsType.Add 24, "EMAIL" dicADsType.Add 25, "NT_SECURITY_DESCRIPTOR" dicADsType.Add 26, "UNKNOWN" Const ADS_PROPERTY_CLEAR = 1 Const ADS_PROPERTY_UPDATE = 2 Const ADS_PROPERTY_APPEND = 3 Const ADS_PROPERTY_DELETE = 4 Dim objPropValue 'An individual property value within a loop Dim objPropEntry 'An ADSI PropertyEntry object Dim objObject 'The object whose property list we wish to investigate Dim strText 'A text string used to display results in one go Dim intPropCount 'The number of properties in Dim intIndex 'The index used while looping through the property list Dim intCount 'Used to display property values in a numbered sequence '********************************************************************** 'Uncomment one of these lines and modify it to your own environment. 'The first uses the LDAP namespace; the second uses the WinNT namespace. '********************************************************************** ' Set objObject = GetObject("LDAP://cn=administrator,cn=users,dc=mycorp,dc=com") ' Set objObject = GetObject("WinNT://WINDOWS/Managers,Group") objObject.GetInfo if (Err.Number > 0) Then Wscript.Echo "Object not found, returning..." Wscript.Quit End if '********************************************************************** 'Write out the current property cache total to the string that is 'storing output '********************************************************************** intPropCount = objObject.PropertyCount strText = "There are " & intPropCount & _ " values in the property cache." & vbCrLf '********************************************************************** 'The extra vbTabs used in the first loop are to space the results so 'that they are nicely formatted with the list of values in the second loop '********************************************************************** For intIndex = 0 To (intPropCount-1) Set objPropEntry = objObject.Item(intIndex) strText = strText & objPropEntry.Name & vbCrLf strText = strText & vbTab & "Type:" & vbTab & vbTab & _ dicADsType.Item(objPropEntry.ADsType) & vbCrLf '********************************************************************** 'Go through each property value in the property entry and use the AdsType 'to print out the appropriate value, prefixed by a count (intCount), i.e.: ' ' Value #1: Vicky Launders ' Value #2: Alistair Lowe-Norris ' Value #3: Robbie Allen '********************************************************************** intCount = 1 For Each objPropValue In objPropEntry.Values If (dicADsType(objPropValue.ADsType) = "STRING") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.DNString & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "CASE_EXACT_STRING") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.CaseExactString & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "CASE_IGNORE_STRING") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.CaseIgnoreString & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "PRINTABLE_STRING") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.PrintableString & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "NUMERIC_STRING") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.NumericString & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "BOOLEAN") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & CStr(objPropValue.Boolean) & vbCrLf ElseIf (dicADsType(objPropValue.ADsType) = "INTEGER") Then strText = strText & vbTab & "Value #" & intCount & ":" _ & vbTab & objPropValue.Integer & vbCrLf End If intCount=intCount+1 Next Next WScript.Echo strText This script displays every value in the property cache for an object. However, there may come a time when you wish to see the entire potential property cache for an object and list which of all possible values have been set. To do that, you need to query the formal schema class definition for the object. This leads us to the final section on the property cache. 19.2.7 Walking the Property Cache Using the Formal Schema Class DefinitionThere is one other way to walk the property list for a particular object: using its schema class details. Chapter 4 explained how the schema is the blueprint for objects in Active Directory. As each schema class actually is stored in Active Directory, you can navigate the object's properties by using the IADsClass interface to display each individual item according to its formal name in the schema class. To do this, we first obtain a reference to the object in the normal manner. We then obtain a reference to the schema class for that object. We can do this using the IADs::Schema property method, which returns the full ADsPath of the schema class. For example, the user objectclass in the mycorp.com domain has the following schema ADsPath: LDAP://cn=User,cn=Schema,cn=Configuration,dc=mycorp,dc=com Then we can use the IADsClass::MandatoryProperties and IADsClass::OptionalProperties methods to retrieve the appropriate properties. The following example nicely brings together IADs::GetEx for retrieving multiple properties and writing to a file, which is required due to the large number of properties. Example 19-8 uses On Error Resume Next because all properties may not display, and the program will fail if any do not. The script also differs from the previous script in that it lists all possible properties and whether they've been set. The previous example listed only those that had been set. The script is also generic; it will print out the property cache for any object class. Just change the ADsPath passed to GetObject. Example 19-8. Walking the property cache using the formal schema class definitionOption Explicit '********************************************************************** 'Force error checking within the code using the Err.Number property 'method in approaches 2 and 3 '********************************************************************** On Error Resume Next '********************************************************************** 'Declare the constants and variables '********************************************************************** Dim objObject 'Active Directory object Dim objClass 'ADSI Class object Dim objProp 'An individual property Dim intCount 'Incremental counter for display Dim fileadsect 'A FileSystemObject Dim outTextFile 'A TextStream Object '********************************************************************** 'Create a VBScript file object and use it to open a text file. The 'second parameter specifies to overwrite any existing file that exists. '********************************************************************** Set fileadsect = CreateObject("Scripting.FileSystemObject") Set outTextFile = fileadsect.CreateTextFile("c:\out.txt", TRUE) '********************************************************************** 'Bind to the object and get a pointer to the appropriate schema class, 'i.e., User in this case '********************************************************************** Set objObject = GetObject("LDAP://cn=administrator,cn=Users,dc=mycorp,dc=com") Set objClass = GetObject(objObject.Schema) intCount = 1 '********************************************************************** 'Iterate through all the mandatory properties '********************************************************************** For Each objProp in objClass.MandatoryProperties EnumerateProperties objProp, outTextFile, objObject intCount=intCount+1 Next '********************************************************************** 'Iterate through all the optional properties '********************************************************************** For Each objProp in objClass.OptionalProperties EnumerateProperties objProp intCount=intCount+1 Next outTextFile.Close '********************************************************************** 'Subroutine EnumerateProperties '********************************************************************** Sub EnumerateProperties(ByVal objProp, ByVal tsFile, ByVal objObj) Dim objProperty 'ADSI Property object Dim arrElement 'Array of elements '********************************************************************** 'Get pointer to the schema property object '********************************************************************** Set objProperty = GetObject("LDAP://Schema/" & objProp) '********************************************************************** 'Check whether property requires GetEx using IADsProperty::MultiValued '********************************************************************** If objProperty.MultiValued Then tsFile.WriteLine intCount & ") " & objProp & _ " (" & objProperty.Syntax & ") (MULTI-VALUED)" '********************************************************************** 'Check whether array returned from GetEx is empty using VBScript function '********************************************************************** If (IsEmpty(objObj.GetEx(objProp))) Then tsFile.WriteLine vbTab & "= " & "NO VALUES SET!" Else For Each arrElement in objObj.GetEx(objProp) tsFile.WriteLine vbTab & "= " & arrElement Next End If Else tsFile.WriteLine intCount & ") " & objProp _ & " (" & objProperty.Syntax & ")" Err.Clear If Err=0 Then tsFile.WriteLine vbTab & "= " & objObj.Get(objProp) Else tsFile.WriteLine vbTab & "= " & "Not Set!" End If End If End Sub |
[ Team LiB ] |