Share via


嗨,Scripting Guy!

嗨,Scripting Guy!

歡迎使用 TechNet 專欄,Microsoft Scripting Guys 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

還有,別忘了瞧瞧全新經過改良的嗨,Scripting Guy!過往文件

今天的問題:如何擷取在其名稱當中有特定字的 OU 清單?


如何擷取在其名稱當中有特定字的 OU 清單?

嗨,Scripting Guy!我們的網域裡面有許多 OU 在 OU 名稱中都有「Servers」一字。我要如何擷取這些 OU 清單呢?

-- AM

AM,您好。我們當中一位 Scripting Guy 有個 15 歲的兒子,每次當他聽到他爸爸述說過去輝煌的故事時,總會轉動著眼珠子說:「你就像那些活在過去的老頭子。」(當然啦,這個 Scripting Son 幾乎同時說出:「記得我十歲的時候,在對抗落磯隊打出的那隻全壘打嗎?」不過好像就是不一樣)。

我們之所以會提到這,是因為您的問題帶我們回到舊時美好時光,回到《嗨,Scripting Guy!》專欄的輝煌時代。當時似乎每個我們收到的問題都有相同的答案:要找東西,搜尋 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, Where's My Printer?》(英文),這個系列說明了 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 子句來指定搜尋的條件,在本例中,要確定兩件事:

  • objectCategory 等於 organizationalUnit。您可能已經猜到,objectCategory 等於 organizationalUnit 的物件會是個 OU。這個部分的查詢會淘汰使用者、電腦、群組、站台、子網路,以及任何存放在 Active Directory 的其他種物件。
  • 在其 Name 屬性中含有「Servers」一字的 OU。請注意萬用字元 (星號) 的使用。*Servers* 的語法基本上是說「我們要在 Name 屬性中任何地方尋找 Servers 一字,我們不在乎 Servers 前面是否有什麼 (第一個星號),也不在乎 Servers 後面是否有什麼 (第二個星號)。我們要的是任何在其名稱當中任一處有 Servers 一字的 OU。」

    我們當然可以修改此一語法,像要是只想搜尋以 Servers 為開頭的名稱呢 (Servers-1、Servers-2 等等)?那麼可以用:Servers*。如您所見,在本例中,我們的名稱必須以 Servers 一字為開頭,我們不管後面是什麼。如果想要搜尋以 Servers 一字結尾的名稱 (Asian Servers、North America Servers 等等),就可以使用此語法:*Servers。這跟使用萬用字元搜尋檔案或資料夾實在沒什麼兩樣,您可能已經做過好幾萬次了。

定義好查詢之後,會呼叫 Execute 方法,這實際上會執行查詢並傳回一個資料錄集,當中包含所有在 Name 中含有 Servers 一字的 OU。接著會對資料錄集執行迴圈,然後針對每個 OU 回應 ADsPath。就是這麼簡單!

順便一提,通常是不建議您搜尋在字串當中的文字 (*Servers*),因為這類的搜尋可能不僅耗用資源,而且也會花網域控制站好一段時間來處理。在這裡沒有這個問題是因為我們假設您沒有上百萬個 OU 要檢查,通常網域有的 OU 比使用者或群組少很多。因此,我們不覺得此搜尋會造成任何問題。

這算回答了您的問題嗎?很好。雖然您沒問,不過我們肯定您想要聽聽我們幾乎是單手打敗漢佛高中那次遙遙領先的戰績,還被排名為州內第一的棒球隊,喔!好啦,要是 Scripting Son 也想談談他在這一季的全壘打,您最好也別聽他的 (雖然那是一次漂亮的打擊,這提醒 Scripting Dad 那天在里奇蘭…)。


如需詳細資訊

查看嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首