objCommand.CommandText = _
"SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE OU <> 'TestLab OU' AND " _
& "objectCategory='computer'"
這個辦法的確很不錯,只不過有點問題:Active Directory 電腦帳戶中並沒有名叫 OU 的屬性;換言之,您不能在 WHERE 子句中使用 OU。A 計畫講了半天,可是行不通。
當然,您這時可能會想「那麼,可不可以用辨別名稱 (DN) 呢」?畢竟,電腦的 DN (例如 CN=atl-ws-01、OU=Test LabOU、DC=fabrikam 以及 DC=com) 會包含電腦帳戶所屬 OU 的名稱。難道我們不能像下面這樣對 DN 進行萬用字元搜尋嗎?
objCommand.CommandText = _
"SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE distinguishedName <> " _
" '*OU=Finance' AND objectCategory='computer'"
非常遺憾,這樣也行不通。因為 DN 是一種「建構的」屬性。DN 並不是實際儲存在 Active Directory 中,它是在您要求的時候臨時建構出來的。因此,您不能對 distinguishedName 屬性進行萬用字元搜尋。而且,您也不用再問同樣含有 OU 名稱的 ADsPath 屬性了;您也不能對 ADsPath 進行萬用字元搜尋。
事實上,就我所知,唯一的辦法是執行一次搜尋,傳回「所有」電腦的清單。當您取得這個清單之後,您可能還要對它做一些處理 (我們暫時假設您只是要在螢幕上列出電腦的名稱)。不過,在對清單中的電腦進行任何處理之前,我們的指令碼必須先檢查 DN 中有沒有目標字串 (例如 OU=Test Lab OU)。如果有,指令碼會略過這部電腦,然後跳到清單中的下一部電腦繼續進行。如果找不到目標字串,指令碼便會呼叫這部電腦的名稱。
仔細看看下面的實際指令碼,可能會讓您更有概念:
On Error Resume Next
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 Name, distinguishedName FROM 'LDAP://dc=fabrikam,dc=com' " _
& "WHERE objectCategory='computer'"
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
intTestOU = InStr(objRecordSet.Fields("distinguishedName").Value, "OU=Test Lab OU")
If intTestOU = 0 Then
Wscript.Echo objRecordSet.Fields("Name").Value
End If
objRecordSet.MoveNext
Loop
我們要特別注意的是下面這幾行程式碼:
intTestOU = InStr(objRecordSet.Fields("distinguishedName").Value, "OU=Test Lab OU")
If intTestOU = 0 Then
Wscript.Echo objRecordSet.Fields("Name").Value
End If
我們在這裡要做的,就是用 InStr 函式檢查電腦的 DN 中是否有字串 OU=TestLab OU。如果有這個字串,intTestOU 便會設定成這個字串開始的字元位置。例如,在 DN CN=atl-ws-01、OU=Test LabOU、DC=fabrikam 以及 DC=com 中,intTestOu 會設定為 14,因為我們的目標子句是從字串中的「第 14 個」字母開始。
但是,萬一 intTestOU 等於零怎麼辦?這種情況只表示一件事情:找不到目標子句。換言之,也就表示這部特定電腦「不是」在「測試實驗室 OU」中,所以我們可以放心地呼叫這部電腦的名稱。如此一來,我們就可以呼叫所有電腦的名稱,但「排除」了「測試實驗室 OU」中的電腦。
就如同我先前說過的,這種方式可以完成工作,但是並不是很高明的辦法。不過,即使不高明卻仍然很好用,不是嗎?
或者,您也可以將 OU 名稱儲存在某個未使用的電腦帳戶屬性中;例如,您可以將 OU 名稱記錄在描述屬性中。這樣一來,您就「可以」利用類似下面的查詢搜尋這個屬性了:
objCommand.CommandText = _
"SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE objectCategory='computer' " & _
"AND description<>'Test Lab OU'"
這種方式非常好用;不過萬一您要將電腦移到新的 OU,可別忘了變更這個描述屬性的數值。 |