|
In this article,
I will show you how you can use VBScript and ADO to query the Active
Directory to find a single or multiple objects. The search methods
outlined here are used in almost every script and Visual Basic
application that queries the AD for objects. Higher-level
languages, like C++, normally use the
IdirectorySearch interface,
which is not available to lower level languages and scripting
interfaces. The search methods shown here will make it very easy to
find and work with objects in the AD no matter which OU they maybe
located in.
In NT you could
easily access an object with ADSI using the
WinNT provider by doing
Set
objUser = GetObject("WinNT://altered/sherrja").
However, you are only able to get at the NT properties when using
the WinNT
provider. In order to get at the ?AD only? properties you must used
the LDAP
provider. Since objects are no longer stored in one container in
the AD you need the full path to the object before you can bind to
it with
LDAP. Therefore, you need
someway to query the AD with a known property, or properties, and
get the path to an object so you can get additional properties of
that object and\or make changes to that object.
In order to get
at objects from the AD we are going to use ADO (ActiveX Data
Objects). ADO allows us to execute SQL like statements,
SELECT * FROM *,
to query the AD for objects and properties.
The first thing we need to do is open
a connection to the AD using ADO. This is done with the lines below
where the first one creates a connection to the AD via ADO, and then
the provider is set to
ADsDSOObject, which is the
OLE DB provider in ADSI. Last, the connection is opened.
-
Set objConnection =
CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory
Provider"
Next, we need to create a
Command
object that is used to issue queries to the AD via the ADO
connection created above. We then pass the
Command
are current connection to ADO that was created above.
-
Set objCommand =
CreateObject("ADODB.Command")
Set objCommand.ActiveConnection =
objConnection
Now that we have the
Command
object created and open we can pass it the search string of the
objects we are looking for. The search string supports queries in a
SQL dialect format. In the example below, we are looking for a
user objects that have a department set to Sales. The
SELECT
AdsPath,cn tells the AD to
return the
AdsPath and
cn
fields of the objects found. Next
FROM 'LDAP://DC=corp,DC=com?
set where the search should be carried out, in this case the root of
the CORP domain will be the starting point for the search. Last we
use the
WHERE statement to set the two
fields we will be searching on,
objectClass
and
department.
-
objCommand.CommandText = ?SELECT AdsPath,cn FROM 'LDAP://DC=corp,DC=com'
WHERE objectClass = 'User' AND department = 'Sales'?
Besides the search string, we can pass
other properties to the
Command
object that controls how the search is carried out. Below we set
the
search scope so all sub OU are queried, since we are starting
the search at the root of the AD we need to at least search one
level deep. The 2 (ADS_SCOPE_SUBTREE) indicates that the specified
location and all sub OUs should be searched. Next, we set the
maximum number of records to return each time from the AD. This
will limit the results to 1,000 rows of data at a time, once we
process the last row AD will return the next 1,000 records. Last,
we set how long the query should wait before returning the results
that have been collected so far. All three of these settings are
optional, the default is to search all sub OUs, return only the
first 1,000 rows of data, and wait until the page size has been
filled or all values have been returned.
-
objCommand.Properties("searchscope") =
2
objCommand.Properties("Page Size") =
1000
objCommand.Properties("Timeout") = 15
Now that we have the query and all the
properties set, we now need to execute the query. This is done with
the
Execute method. The results,
1000 rows at a time, are then returned to the
objRecordSet
variable.
-
Set objRecordSet = objCommand.Execute
Therefore, we now have the results
from our query let us look at what was retuned. First, we use the
MoveFirst method to get the
first record. If there was no data returned this first line will
return an error. Assuming we do have additional records we then
start a loop that will continue until the last record has been read
in. Inside the loop we retrieve the
AdsPath
and cn
fields from the current record; the
AdsPath
contains the fully qualified LDAP path to the object. Then with the
objPath
set, we then use
GetObject
to retrieve the object from the AD so we can get at other properties
of the object. On the next line, we display the
samAcccountName
and cn
attribute of that object in a
pop-up message. Last, we use the
MoveNext method to retrieve
the next record.
-
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
AdsPath =
objRecordSet.Fields("AdsPath")
cn = objRecordSet.Fields("cn")
Set objObject = GetObject(AdsPath)
MsgBox ?Logon name: ? &
objObject.samAccountName & ? for ? & cn
objRecordSet.MoveNext
Loop
Below is the
entire code covered above that is used to find all users with
?Sales? in their department field. See the include script for a
more flexible way for searching for object by using the code below
as a function. This way you can carry easily out a search whenever
you need to find all objects with certain attributes.
-
Set objConnection =
CreateObject("ADODB.Connection")
Set objCommand =
CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory
Provider"
Set objCommand.ActiveConnection =
objConnection
objCommand.CommandText = "SELECT
AdsPath,cn FROM 'LDAP://DC=corp,DC=com' WHERE objectClass = 'User'
AND department = 'Sales'"
objCommand.Properties("searchscope") =
2
objCommand.Properties("Page Size") =
1000
objCommand.Properties("Timeout") = 15
objCommand.Properties("Cache Results")
= False
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
objPath =
objRecordSet.Fields("AdsPath")
Set objObject = GetObject(objPath)
MsgBox "Logon name: " &
objObject.samAccountName & " for " & cn
objRecordSet.MoveNext
Loop
The included
script includes two search methods, one for returning a single
record and the other for returning multiple records similar to the
steps outlined above. In addition, the method for returning
multiple records is written as a function so other parts of your
code can call it and get all values that match the search fields you
pass it. The single search method is also a function and it will
return the ADsPath of the first object that matches the search
criteria given. Both of these functions are very useful when
working with objects in the AD. |