使用 ActiveX 数据对象 (ADO) 进行搜索

ActiveX 数据对象 (ADO) 模型由下表列出的对象组成。

Object 说明
Connection 与 OLE DB 数据源(如 ADSI)的开放连接。
命令 定义要对数据源运行的特定命令。
参数 用于为命令对象提供任何参数的可选集合。
RecordSet 表、命令对象或 SQL 语法中的一组记录。 创建记录集时不需要任何基础连接对象。
字段 记录集中的单个数据列。
属性 由 ADO 提供程序提供的值的集合。
错误 包含有关数据访问错误的数据。 在单个操作中发生错误时刷新。

ADO 要与 ADSI 通信,必须至少有两个 ADO 对象:ConnectionRecordSet。 这些 ADO 对象分别用于验证用户身份和枚举结果。 通常,你还将使用 Command 对象来维护活动连接、指定查询参数(如页面大小和搜索范围)以及执行查询。 有关搜索筛选器语法的详细信息,请参阅搜索筛选器语法

Connection 对象加载 OLE DB 提供程序,并验证用户凭据。 在 Visual Basic 中,使用“ADODB.Connection”调用 CreateObject 函数,以创建 Connection 对象的实例,然后将 Connection 对象的 Provider 属性设置为“ADsDSOObject”。 “ADODB.Connection”是 Connection 对象的 ProgID,而“ADsDSOObject”是 ADSI 中 OLE DB 提供程序的名称。 如果未指定凭据,则使用当前登录用户的凭据。

下面的代码示例演示如何创建 Connection 对象的实例。

Set con = CreateObject("ADODB.Connection")
con.Provider = "ADsDSOObject"

下面的代码示例演示如何创建 Connection 对象的实例。

<%
Set con = Server.CreateObject("ADODB.Connection")
con.Provider = "ADsDSOObject"
%>

下面的代码示例演示如何创建 Connection 对象的实例。 请注意,必须将 ADO 类型库 (msadoXX.dll) 作为 Visual Basic 项目的引用之一包含在内。

Dim Con As New Connection
con.Provider = "ADsDSOObject"

通过设置 Connection 对象的属性来指定用户身份验证数据。 下表列出了 ADSI 支持的用户身份验证属性。

properties 说明
“User ID” 一个字符串,用于标识执行搜索时使用其安全上下文的用户。 有关用户名字符串格式的详细信息,请参阅 IADsOpenDSObject::OpenDSObject。 如果未指定,默认值为登录用户或调用进程所模拟的用户。
“Password” 一个字符串,指定由“User ID”标识的用户的密码。
“Encrypt Password” 一个布尔值,用于指定是否对密码进行加密。 默认值为 false。
“ADSI Flag” 来自 ADS_AUTHENTICATION_ENUM 枚举的一组标志,用于指定绑定身份验证选项。 默认值为零。

下面的代码示例显示了在创建 Command 对象之前如何设置属性。

Set oConnect = CreateObject("ADODB.Connection")
oConnect.Provider = "ADsDSOObject"
oConnect.Properties("User ID") = stUser
oConnect.Properties("Password") = stPass
oConnect.Properties("Encrypt Password") = True
oConnect.Open "DS Query", stUser, stPass

第二个 ADO 对象是 Command 对象。 Command 对象的 ProgID 是“ADODB.Command”。 通过此对象,可以使用活动连接向 ADSI 发出查询语句和其他命令。 Command 对象使用其 ActiveConnection 属性来保持活动连接。 它还维护 CommandText 属性以保存用户发出的查询语句。 查询语句使用 SQL 方言LDAP 方言

以下代码示例展示了如何创建 Command 对象。

Set command = CreateObject("ADODB.Command")
Set command.ActiveConnection = oConnect
command.CommandText = 
"SELECT AdsPath, cn FROM 'LDAP://DC=Fabrikam,DC=com' WHERE objectClass = '*'"

在以下代码示例中,将 ADO 类型库 (msadoXX.dll) 作为引用之一包含在内。

Dim command As New Command
Set command.ActiveConnection = oConnect
command.CommandText = "<LDAP://DC=Fabrikam,DC=com>;(objectClass=*);AdsPath, cn; subTree"

Command 对象的搜索选项通过设置 Properties 属性来指定。 下表列出了 Properties 可接受的命名属性。

命名的属性 说明
“Asynchronous” 一个布尔值,用于指定是同步搜索还是异步搜索。 默认值为 False(同步)。 同步搜索会阻止,直到服务器返回全部结果,或者对于分页搜索,则是整个页面。 异步搜索会阻止,直到有一行搜索结果可用,或者直到“Timeout”属性指定的时间过去。
”Cache results“ 一个布尔值,用于指定是否在客户端缓存结果。 默认值为 true;ADSI 会缓存结果集。 对于大型结果集,可能需要关闭此选项。
“Chase referrals” ADS_CHASE_REFERRALS_ENUM 中的一个值,用于指定搜索如何跟踪引用。 默认值为 ADS_CHASE_REFERRALS_NEVER。有关此属性的详细信息,请参阅引荐
“Column Names Only” 一个布尔值,表示搜索应只检索已赋值的属性名称。 默认值为 false。
“Deref Aliases” 一个布尔值,用于指定是否解析找到的对象的别名。 默认值为 false。
“Page size” 一个整数值,用于打开分页并指定结果集中返回对象的最大数量。 默认值为无页面大小。 有关详细信息,请参阅检索大型结果集
“SearchScope” ADS_SCOPEENUM 枚举中的一个值,用于指定搜索范围。 默认值为 ADS_SCOPE_SUBTREE
“Size Limit” 一个整数值,指定搜索的大小限制。 对于 Active Directory,大小限制指定了返回对象的最大数量。 当达到大小限制时,服务器会停止搜索,并返回累积的结果。 默认值为无限制。
“Sort on” 一个字符串,用于指定以逗号分隔的属性列表作为排序键。 此属性仅适用于支持用于服务器端排序 LDAP 控件的目录服务器。 Active Directory 支持排序控制,但它会影响服务器性能,尤其是在结果集较大的情况下。 请注意,Active Directory 仅支持单个排序键。 默认值为不排序。
“Time Limit” 一个整数值,指定搜索的时间限制(以秒为单位)。 达到时间限制后,服务器将停止搜索并返回累积的结果。 默认无时间限制。
“Timeout” 一个整数值,指定客户端超时值(以秒为单位)。 此值表示客户端在停止搜索前等待服务器结果的时间。 默认值为无超时。

下面的代码示例显示了如何设置搜索选项。

Const ADS_SCOPE_ONELEVEL = 1
Const ADS_CHASE_REFERRALS_EXTERNAL = &H40

Dim Com As New Command
 
Com.Properties("Page Size") = 999
Com.Properties("Timeout") = 30     ' Seconds
Com.Properties("searchscope") = ADS_SCOPE_ONELEVEL
Com.Properties("Chase referrals") = ADS_CHASE_REFERRALS_EXTERNAL
Com.Properties("Cache Results") = False     ' Do not cache the result set.

第三个 ADO 对象是 RecordSet。 在调用 Command 对象上的 Execute 方法时,就会获得此对象。 RecordSet 对象的主要功能是枚举结果集和获取数据。 结果集可包含具有单个或多个值的属性值。 获取单值属性非常简单,类似于获取关系数据库中的列值,例如:

Fields('name').Value

然而,获取具有多个值的属性则更具挑战性。 在这种情况下,Field.Value 是一个数组,你必须检查数组的下限和上限,如以下代码示例所示。

Set rs = Com.Execute
 
For i = 0 To rs.Fields.Count - 1
    Debug.Print rs.Fields(i).Name, rs.Fields(i).Type
Next i
 
'--------------------------
' Navigate the record set.
'--------------------------
rs.MoveFirst
lstResult.Clear      ' Clear the user interface.
While Not rs.EOF
For i = 0 To rs.Fields.Count - 1
    ' For Multi Value attribute
    If rs.Fields(i).Type = adVariant And Not (IsNull(rs.Fields(i).Value)) Then
        Debug.Print rs.Fields(i).Name, " = "
        For j = LBound(rs.Fields(i).Value) To UBound(rs.Fields(i).Value)
            Debug.Print rs.Fields(i).Value(j), " # "
            lstResult.AddItem rs.Fields(i).Value(j)
        Next j
    Else
        ' For Single Value attribute.
         Debug.Print rs.Fields(i).Name, " = ", rs.Fields(i).Value
         lstResult.AddItem rs.Fields(i).Value
    End If
Next i
rs.MoveNext
Wend

下面的代码示例禁用了 LDAP 服务器上的用户帐户。

Dim X as IADs
Dim con As New Connection, rs As New Recordset
Dim MyUser As IADsUser
 
con.Provider = "ADsDSOObject"
con.Open "Active Directory Provider", "CN=Test,CN=Users,DC=Fabrikam,DC=COM,O=INTERNET", "Password"
Set rs = con.Execute("<LDAP://MyMachine/DC=MyDomain,DC=Fabrikam,DC=com>;(objectClass=User);ADsPath;onelevel")
 
While Not rs.EOF
    ' Bind to the object to make changes 
    ' to it because ADO is currently read-only.
    MyUser = GetObject(rs.Fields(0).Value)
    MyUser.AccountDisabled = True
    MyUser.SetInfo
    rs.MoveNext
Wend

有关 ADO 对象模型的详细信息,请参阅 Microsoft ActiveX 数据对象