嗨,Scripting Guy!

嗨,Scripting Guy!

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

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

今天的問題:如何列出 Active Directory 內的所有站台,以及站台內的所有伺服器?


如何列出 Active Directory 內的所有站台,以及站台內的所有伺服器?

嗨,Scripting Guy!如何列出 Active Directory 內的所有站台,以及站台內的所有伺服器?

-- DW

DW,您好。您真是考倒我們了。如果是使用者和群組,我們還可以回答,至少我們對使用者和群組稍微有點瞭解。如果是電腦帳戶或組織單位 (OU),也沒問題。但牽涉到站台、站台連結等主題時,我們就開始緊張了,誰教我們壓根兒搞不懂那是什麼東西,更遑論寫程式了。

但是 Scripting Guys 是不可能因為缺乏知識或瞭解就怯步了。還是絞盡腦汁,給各位列出下面的指令碼。它可以列出 Active Directory 內所有的站台,以及每個站台內的伺服器:

On Error Resume Next
Set objRootDSE = GetObject("LDAP://RootDSE")
strConfigurationNC = objRootDSE.Get("configurationNamingContext")
 
strSitesContainer = "LDAP://cn=Sites," & strConfigurationNC
Set objSitesContainer = GetObject(strSitesContainer)
objSitesContainer.Filter = Array("site")
 
For Each objSite In objSitesContainer
    Wscript.Echo objSite.CN
    strSiteName = objSite.Name
    strServerPath = "LDAP://cn=Servers," & strSiteName & ",cn=Sites," & _
        strConfigurationNC
    Set colServers = GetObject(strServerPath)
 
    For Each objServer In colServers
        WScript.Echo vbTab & objServer.CN
    Next
    Wscript.Echo
Next

這裡的動作是什麼呢?(老實說,我們不是故意裝不懂,希望有誰能給我們解釋一下!) 我們先寫兩行程式碼,連結到 Active Directory 的根目錄,然後再連到 Configuration 容器 (configuringNamingContext):

Set objRootDSE = GetObject("LDAP://RootDSE")
strConfigurationNC = objRootDSE.Get("configurationNamingContext")

為什麼要這樣起頭呢?因為 Configuration 容器包含了 Active Directory 實體架構和配置的資訊,我們可以在這裡找到站台和每個站台內含的伺服器。連結到 Active Directory 根目錄 (rootDSE) 然後使用 Get 方法擷取 configurationNamingContext,就可以取得 Configuration 容器的 Active Directory 路徑,無須擔心我們的網域名稱為何。


附註:這是什麼意思?這表示您可以直接使用這份指令碼,不用將 fabrikam.com 改寫為您網域的名稱,讀者也看到了,指令碼裡根本就不參照 fabrikam.com (或任何網域名稱)。


下一步是擷取 Active Directory 內所有的站台。這個動作是由這段程式碼進行:

strSitesContainer = "LDAP://cn=Sites," & strConfigurationNC
Set objSitesContainer = GetObject(strSitesContainer)
objSitesContainer.Filter = Array("site")

第一行我們先把 ADsPath 建構為 Sites 的容器,把 LDAP://cn=Sites 和 configurationNamingContext 合併。我們使用 GetObject 方法來繫結到 Container,然後套用 Filter,限制只蒐集 Site 物件內的項目。最後得到的結果是 objSitesContainer 會包含所有 Active Directory 站台。

看來這沒有我們原相想像的困難嘛。下一步要建立一個 For Each 迴圈來循環處理所有回傳的集合。在迴圈裡以 CN 呼叫集合內第一個站台,然後將站台的名稱 (以類似 CN=Default-First-Site-Name 的格式) 儲存在 strSiteName 變數內:

Wscript.Echo objSite.CN
strSiteName = objSite.Name

結果我們發現每個 Active Directory 站台裡有個 Servers 容器,每個 Servers 容器裡又包含指派給該站台的伺服器清單。現在要替第一個站台連接到 Servers 容器,我們使用下面這行程式碼建立一個 ADsPath,將路徑儲存在 strServerPath 變數內:

strServerPath = "LDAP://cn=Servers," & strSiteName & ",cn=Sites," & _
    strConfigurationNC

ADsPath 準備好了以後,就可以使用這行程式碼,替第一個伺服器繫結到 Servers 容器:

Set colServers = GetObject(strServerPath)

目前一切都進行得很順利。下一步要建立第二個 For Each 迴圈來循環處理 Servers 容器內所有的項目集合。我們只要針對集合內的每一個伺服器回傳伺服器 CN:

For Each objServer In colServers
    WScript.Echo vbTab & objServer.CN
Next

差點忘了,還要在伺服器名稱前放一個定位字元 (vbTab):您只要看看輸出範例就知道我們為何要這麼做了。

大功告成!現在我們已經用呼叫傳回了第一個網站的名稱,以及指派給該站台的伺服器名稱。只要對集合內的第二個伺服器依樣畫葫蘆,進行迴圈處理,直到跑遍所有的站台,並傳回各站台裡所有的伺服器名稱就行了。一切都完成時,會得到類似下面的輸出結果:

Default-First-Site-Name
    atl-dc-01
    atl-dc-02

European-Site lon-dc-01 lon-dc-02 par-dc-01 bru-dc-01 bru-dc-02

不賴吧?如果我們對這個主題更清楚,寫出來的指令碼就更沒話說了。


如需詳細資訊

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

 

回到頁首 回到頁首