您好,AM。一位脚本专家有一个 15 岁的儿子,每当听他父亲讲起过去的事,总是转着眼睛说:“您就是仍生活在过去的那些老人之一”。(当然,这位脚本专家的儿子会用同样的语气说:“还记得我 10 岁时对洛基队的本垒打吗?”但这多少有些不同。)
我们提起这个是因为您的问题把我们带回了过去,回到了嗨,脚本专家!专栏的光辉岁月。那时,似乎我们收到问题中每隔一个就会有同样的答案:您可以通过搜索 Active Directory 找到您要的答案。我们这么做是因为搜索 Active Directory 是系统管理员的一个令人难以置信的强大工具,抑或是因为我们太懒,只想一遍遍重复给出相同答案呢?尽管我们确实懒惰,但事实却是 Active Directory 的 ADO 搜索对系统管理员来说其用无穷。如果您需要用户帐户、组、计算机或者电话号码的列表,或者任何东西的列表,很有可能您会发现这些信息就存储在 Active Directory 中。
那么,如果有必要的话就请转转眼睛叹口气,但这就是您问题的答案所在:您可以通过搜索 Active Directory 找到您要的答案。实际上,您可以通过类似以下的脚本检索名称中含有“Servers”的 OU 列表:
Const ADS_SCOPE_SUBTREE = 2
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.CommandText = _
"SELECT ADsPath FROM 'LDAP://dc=fabrikam,dc=com' " & _
"WHERE objectCategory='organizationalUnit' AND Name = '*Servers*'"
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
Wscript.Echo objRecordSet.Fields("ADsPath").Value
objRecordSet.MoveNext
Loop
今天我们不详细回顾此脚本;如果您对搜索 Active Directory 不太熟悉,可以看一下我们的两篇系列文章 Dude,我的打印机在哪儿?(英文),该系列文章解释了 ADODB.Connection 对象和 Searchscope 以及此脚本中出现的您不熟悉的所有其他代码。相反,我们只阐述最终实际返回 OU 列表的 SQL 查询:
objCommand.CommandText = _
"SELECT ADsPath FROM 'LDAP://dc=fabrikam,dc=com' " & _
"WHERE objectCategory='organizationalUnit' AND Name = '*Servers*'"
我们要做的就是搜索 fabrikam.com 域,检索 ADsPath 属性。(当然,我们也可以选择任何其他属性,甚至是多个属性。之所以选择 ADsPath 是因为了解对象的 ADsPath 后就可以轻易绑定到该对象,并检索其所有属性值。)这部分相当易懂;我们真正感兴趣的是 WHERE 子句:
WHERE objectCategory='organizationalUnit' AND Name = '*Servers*'
我们使用 WHERE 子句指定搜索条件,在此示例中我们要寻找两个对象:
| • |
等同于 organizationalUnit 的 objectCategory。正如您可能想到的,objectCategory 等于 organizationalUnit 的对象即是一个 OU。此部分查询排除了 Active Directory 上存储的用户、计算机、组、站点、子网和其他对象。 |
| • |
Name 属性中有 Servers 一词的 OU。注意通配符(星号)的使用。语法 *Servers* 的基本含意是:“我们在 Name 属性的所有位置查找 Servers 一词。我们不管 Servers 一词之前如果有内容的话是什么(第一个星号),也不管 Servers 一词之后如果有内容的话是什么(第二个星号)。我们只需要 Name 属性中有 Servers 一词的所有 OU。”
当然,我们还可以修改这一语法。如果我们只要搜索以 Servers开头的 Name 属性(Servers-1、Servers-2 等)该怎么办?如果这样,我们可以搜索:Servers*。正如您所看到的,此处 Name 必须以 Servers 一词开始;我们不关心其后的内容。如果我们要搜索以 Servers 一词结尾的 Name(Asian Servers、North America Servers 等),使用的语法为:*Servers。这与您可能已经用过无数次的用通配符搜索文件或文件夹完全相同。 |
定义完查询后,我们调用 Execute 方法;从而正式运行查询并返回一个记录集,其中包括 Name 中有 Servers 一词的所有 OU。接着我们遍历记录集,并回显所有这些 OU 的 ADsPath。就这么简单!
顺便说一下,通常不建议搜索在字符串中间出现的文本 (*Servers*);因为此类搜索耗费资源,需要域控制器花费较长时间处理。我们此例中使用是因为我们假定您没有数百万个 OU 要检查;通常域的 OU 要远少于用户或组等。因此,我们预计此搜索不会引起问题。
您为以上解答满意吗?好的。另外,尽管您没问,我们肯定您想听我们几乎单枪匹马就击败汉福德高中的事,那时简直所向无敌,是俄亥俄州排名第一的棒球队,好了。不过,如果那位脚本专家的儿子要讲他本赛季的本垒打,您最好也不要听他的。(尽管那曾是漂亮的一击。它使那位脚本专家想起在里奇兰德的一天,那时他……。)