AD トポロジ検索

Microsoft.AD.Topology.Discovery (Discovery)

フォレスト単位の AD トポロジ検索を実行します。

Knowledge Base article:

概要

AD トポロジ検出ルール。この検出ルールは管理サーバーで実行され、AD フォレスト、サイト、ドメイン、およびドメイン コントローラーを検出します。DC は、管理ノードであるかどうかを問わず、AD フォレスト内で検出されます。

構成

AD トポロジ検出では、すべての DC でエージェント セキュリティ設定 "エージェント プロキシ" が設定されている必要があります。詳細については、AD MP のガイドを参照してください。

追加情報

このバージョンの AD MP は、複数の AD フォレスト トポロジ検出をサポートしていません。この機能は、将来のバージョンの AD MP で実装される予定です。

Element properties:

TargetMicrosoft.SystemCenter.RootManagementServer
EnabledTrue
Frequency86400
RemotableFalse

Object Discovery Details:

Discovered Classes and their attribuets:

Member Modules:

ID Module Type TypeId RunAs 
DiscoveryDataSource DataSource Microsoft.Windows.Server.AD.TopologyDiscoveryDataSource Default

Source Code:

<Discovery ID="Microsoft.AD.Topology.Discovery" Enabled="true" Target="SC!Microsoft.SystemCenter.RootManagementServer" ConfirmDelivery="true" Remotable="false" Priority="Normal">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="Microsoft.Windows.Server.AD.Library.Forest">
<Property TypeID="Microsoft.Windows.Server.AD.Library.Forest" PropertyID="Name"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Forest" PropertyID="SchemaMaster"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Forest" PropertyID="DomainNamingMaster"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Forest" PropertyID="LastDiscovery"/>
</DiscoveryClass>
<DiscoveryClass TypeID="Microsoft.Windows.Server.AD.Library.Site">
<Property TypeID="Microsoft.Windows.Server.AD.Library.Site" PropertyID="Name"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Site" PropertyID="ISTGEnabled"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Site" PropertyID="Subnets"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Site" PropertyID="ISTGRoleHolder"/>
</DiscoveryClass>
<DiscoveryClass TypeID="Microsoft.Windows.Server.AD.Library.SiteLink">
<Property TypeID="Microsoft.Windows.Server.AD.Library.SiteLink" PropertyID="Name"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.SiteLink" PropertyID="Cost"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.SiteLink" PropertyID="ReplicationInterval"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.SiteLink" PropertyID="Transport"/>
</DiscoveryClass>
<DiscoveryClass TypeID="Microsoft.Windows.Server.AD.Library.Domain">
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="Name"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="DefaultNamingContext"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="PDCEmulator"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="RIDMaster"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="InfrastructureMaster"/>
<Property TypeID="Microsoft.Windows.Server.AD.Library.Domain" PropertyID="LastDiscovery"/>
</DiscoveryClass>
</DiscoveryTypes>
<DataSource ID="DiscoveryDataSource" TypeID="Microsoft.Windows.Server.AD.TopologyDiscoveryDataSource">
<IntervalSeconds>86400</IntervalSeconds>
<ApplicationName>%windir%\System32\cscript.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>//nologo $file/ADTopologyDiscovery.vbs$ 0 $MPElement$ $Target/Id$ $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</CommandLine>
<TimeoutSeconds>3600</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<DiscoverAgentOnly>false</DiscoverAgentOnly>
<OpsMgrInstallPath>"%ProgramFiles%\System Center Operations Manager 2007"</OpsMgrInstallPath>
<OpsMgrVersion>$Target/Property[Type="SC!Microsoft.SystemCenter.HealthService"]/Version$</OpsMgrVersion>
<PowershellInstallPath>"%windir%\system32\windowspowershell\v1.0\powershell.exe"</PowershellInstallPath>
<ManagementGroupName>"$Target/ManagementGroup/Name$"</ManagementGroupName>
<VerboseLogging>false</VerboseLogging>
<Files>
<File>
<Name>ADTopologyDiscovery.vbs</Name>
<Contents><Script>'*************************************************************************
' Script Name - AD Topology Discovery
' Description
' Discovers topologies for all forests that have two way trust with
' current forest which RMS belongs to.
' Input parameters: all input parameters are used only to create discovery data object
' (0) sourceType
' (1) sourceID
' (2) managedEntityID
' (3) targetComputerName (not used)
' (4) bDiscoverAgentOnly
' (5) strOpsMgrInstallPath
' (6) strOpsMgrInstallVersion
' (7) strPowershellInstallPath
' (8) strManagementGroupName
' (9) bVerboseLogging
'*************************************************************************

Option Explicit

SetLocale("en-us")

'*************************************************************************
' Constants
'*************************************************************************
const iType_ADContainer = 0
Const iType_Forest = 1
const iType_Domain = 2
Const iType_SiteLink = 3
Const iType_Site = 4
Const iType_DCComputer = 5
Const strScriptName = "ADTopologyDiscovery"

'Event Constants
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4

'Event IDs
Const EVENT_ID_DISCOVERY_INFO = 500
Const EVENT_ID_SCRIPT_ERROR = 1000
Const EVENT_ID_SUCCESS = 5000

Dim oShell, oFso ' The Wscript.Shell and Scripting.FileSystem objects, respectivly
Dim aNames ' An array of agent names (in lowercase FQDN format), only populated when
' DiscoverAgentOnly is set to true
Dim bDiscoverAgentOnly, bVerboseLogging

'*************************************************************************
' Class
' - ADObject class
'*************************************************************************
Class ADObject
Dim iType
Dim iParentType
Dim oObject
Dim oParentInstance
Dim oInstance
Dim oRelationShipInstance
Dim strForestName
Dim strForestDN
Sub Init(ByVal iObjType, ByVal iPType, ByRef strCurrentForestName, ByRef strCurrentForestDN, ByRef oPInstance, ByRef oObj)
iType = iObjType
iParentType = iPType
strForestName = LCase(strCurrentForestName)
strForestDN = strCurrentForestDN
Set oParentInstance = oPInstance
Set oObject = oObj
End Sub

Function CreateInstance(ByRef arrParam, ByRef oDiscData, ByRef ohtDC)
Dim iAddInstanceFlag
iAddInstanceFlag = 1
Select Case iType
Case iType_Forest '//Forest type
Dim oContainerToForestRel
Set oInstance = oDiscData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']$")
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']/Name$", strForestName
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']/SchemaMaster$", arrParam(0)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']/DomainNamingMaster$", arrParam(1)
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Container.contains.Microsoft.Windows.Server.AD.Library.Forest']$", oParentInstance, oInstance, oDiscData)
Case iType_Domain
Set oInstance = oDiscData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']$")
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']/Name$", arrParam(0)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']/DefaultNamingContext$", arrParam(1)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']/PDCEmulator$", arrParam(2)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']/RIDMaster$", arrParam(3)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain']/InfrastructureMaster$", arrParam(4)

If iParentType = iType_Domain Then '//If domain has a trust parent "domain contains domain"
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain.contains.Microsoft.Windows.Server.AD.Library.Domain']$", oParentInstance, oInstance, oDiscData)
Else
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest.contains.Microsoft.Windows.Server.AD.Library.Domain']$", oParentInstance, oInstance, oDiscData)
End If
Case iType_SiteLink '//SiteLink type
Set oInstance = oDiscData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.SiteLink']$")
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']/Name$", strForestName
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.SiteLink']/Name$", arrParam(0)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.SiteLink']/ReplicationInterval$", arrParam(1)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.SiteLink']/Transport$", arrParam(2)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.SiteLink']/Cost$", arrParam(3)
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest.hosts.Microsoft.Windows.Server.AD.Library.SiteLink']$", oParentInstance, oInstance, oDiscData)
Case iType_Site '//Site type
If iParentType = iType_SiteLink Then
If IsEmpty(ohtDC("SITE!" &amp; arrParam(0))) Then
Set oInstance = oDiscData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site']$")
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest']/Name$", strForestName
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site']/Name$", arrParam(0)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site']/ISTGEnabled$", arrParam(1)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site']/ISTGRoleHolder$", arrParam(2)
oInstance.AddProperty "$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site']/Subnets$", arrParam(3)
ohtDC.Add "SITE!" &amp; arrParam(0), oInstance
Else
iAddInstanceFlag = 0
Set oInstance = ohtDC("SITE!" &amp; arrParam(0))
End If
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site.references.Microsoft.Windows.Server.AD.Library.SiteLink']$", oInstance, oParentInstance, oDiscData)
Else '//Only for the relationship with forest. site instance is already created
iAddInstanceFlag = 0
Set oInstance = ohtDC("SITE!" &amp; arrParam(0))
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Forest.hosts.Microsoft.Windows.Server.AD.Library.Site']$", oParentInstance, oInstance, oDiscData)
End If
Case iType_DCComputer '//DC.Computer type
If iParentType = iType_Domain Then
Set oInstance = oDiscData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Server.DC.Computer']$")
oInstance.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", arrParam(0)
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Domain.contains.Microsoft.Windows.Server.DC.Computer']$", oParentInstance, oInstance, oDiscData)
ohtDC.Add "DC!" &amp; arrParam(0), oInstance
ElseIf (iParentType = iType_Site) And (Not IsEmpty(ohtDC("DC!" &amp; arrParam(0)))) Then '//Only for the relationship with site. DC instance is already created, all other cases igored (this can be an issue with ad consistency)
iAddInstanceFlag = 0
Set oInstance = ohtDC("DC!" &amp; arrParam(0))
Set oRelationShipInstance = CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Site.contains.Microsoft.Windows.Server.DC.Computer']$", oParentInstance, oInstance, oDiscData)
Else
CreateInstance = 0
Exit Function
End If
End Select
If iAddInstanceFlag = 1 Then
oDiscData.AddInstance oInstance
End If
oDiscData.AddInstance oRelationShipInstance
CreateInstance = 0
End Function
End Class

'*************************************************************************
' CreateRelationshipInstance
'*************************************************************************
Function CreateRelationshipInstance(ByRef strRelationship, ByRef source, ByRef target, ByRef oDiscData)
Dim oRelationship
Set oRelationship = oDiscData.CreateRelationshipInstance(strRelationship)
oRelationship.Source = source
oRelationship.Target = target
Set CreateRelationshipInstance = oRelationship
End Function

'*************************************************************************
' InitializeEnvironment
'*************************************************************************
Function InitializeEnvironment(ByRef oAPI, ByRef oDiscData, ByRef oADOConn, ByRef oStack)
On Error Resume Next
Err.Clear
Dim oArgs
Dim strSourceType, strSourceID, strManagedEntityID, strTargetComputerName, strOpsMgrInstallPath, strOpsMgrInstallVersion, strPowershellInstallPath, strManagementGroupName
Dim strArguments
Dim argumentIndex
strArguments = ""

Set oAPI = CreateObject("Mom.ScriptAPI")

If Err &lt;&gt; 0 Then
Quit -1
End If
Set oArgs = WScript.Arguments

If oArgs.Count &lt; 10 Then
InitializeEnvironment = 2
Exit Function
End If

strSourceType = oArgs(0)
strSourceID = oArgs(1)
strManagedEntityID = oArgs(2)
strTargetComputerName = oArgs(3)
bDiscoverAgentOnly = CBool(oArgs(4))
strOpsMgrInstallPath = oArgs(5)
strOpsMgrInstallVersion = oArgs(6)
strPowershellInstallPath = oArgs(7)
strManagementGroupName = oArgs(8)
bVerboseLogging = CBool(oArgs(9))

CreateInformationEvent EVENT_ID_DISCOVERY_INFO, _
vbCrLf &amp; _
"Discovery script has been invoked with arguments:" &amp; vbCrLf &amp; _
"SourceType= " &amp; strSourceType &amp; vbCrLf &amp; _
"SourceID= " &amp; strSourceID &amp; vbCrLf &amp; _
"ManagedEntityID= " &amp; strManagedEntityID &amp; vbCrLf &amp; _
"TargetComputerName= " &amp; strTargetComputerName &amp; vbCrLf &amp; _
"DiscoverAgentOnly= " &amp; bDiscoverAgentOnly &amp; vbCrLf &amp; _
"OpsMgrInstallPath= " &amp; strOpsMgrInstallPath &amp; vbCrLf &amp; _
"OpsMgrInstallVersion= " &amp; strOpsMgrInstallVersion &amp; vbCrLf &amp; _
"PowershellInstallPath= " &amp; strPowershellInstallPath &amp; vbCrLf &amp; _
"ManagementGroupName= " &amp; strManagementGroupName &amp; vbCrLf &amp; _
"bVerboseLogging= " &amp; bVerboseLogging ,_
oAPI

Set oDiscData = oAPI.CreateDiscoveryData(oArgs(0), oArgs(1), oArgs(2))
If Err &lt;&gt; 0 Then
InitializeEnvironment = 3
Exit Function
End If

Set oADOConn = CreateObject("ADODB.Connection")
If Err &lt;&gt; 0 Then
InitializeEnvironment = 4
Exit Function
End If
oADOConn.Provider = "ADSDsOOBject"
oADOConn.Open "ADs Provider"
If Err &lt;&gt; 0 Then
InitializeEnvironment = 5
Exit Function
End If
Set oStack = CreateObject("System.Collections.Stack")
If Err &lt;&gt; 0 Then
InitializeEnvironment = 6
Exit Function
End If

If bDiscoverAgentOnly Then
If strOpsMgrInstallPath = "" Then
InitializeEnvironment = 15
Exit Function
End If

If strPowershellInstallPath = "" Then
InitializeEnvironment = 16
Exit Function
End If

CreateInformationEvent EVENT_ID_DISCOVERY_INFO,"Discovering only machines with the Operations Manager agent installed", oAPI
aNames = GetAgentNames(strOpsMgrInstallPath, strOpsMgrInstallVersion, strPowershellInstallPath, strManagementGroupName, oAPI)

If IsNull(aNames) Then
InitializeEnvironment = 14
Exit Function
End If
End If

InitializeEnvironment = 0
End Function

'*************************************************************************
' PrepareInitialStack
' - Prepare all available (two-way trust) RootDSE's
'*************************************************************************
Function PrepareInitialStack(ByRef oADOConn, ByRef oStack, ByRef oDiscData, ByRef oAPI)
On Error Resume Next '//only for this function
Err.Clear
Dim oCurrentRootDSE
Dim oCurrentADObj
Dim cForests
Dim oTempStack '//to keep the order LIFO + LIFO = FIFO
Dim i
Dim oADContainer
Set oADContainer = oDiscData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.AD.Library.Container']$")
Set oTempStack = CreateObject("System.Collections.Stack")
Set oCurrentRootDSE = GetObject("LDAP://RootDSE")
If IsEmpty(oCurrentRootDSE) Then
PrepareInitialStack = 7
Exit Function
End If
Set oCurrentADObj = new ADObject
oTempStack.Push(oCurrentADObj)
oCurrentADObj.Init iType_Forest, iType_ADContainer, DNSNameFromDN(oCurrentRootDSE.Get("defaultNamingContext")), oCurrentRootDSE.Get("defaultNamingContext"), oADContainer, oCurrentRootDSE
Set cForests = LDAPQuery(oCurrentADObj.oObject.Get("defaultNamingContext"), "(&amp; (&amp;(objectCategory=trustedDomain)(trustAttributes=8))(trustDirection=3))", "cn", "subtree", oADOConn, oAPI)
If Not IsEmpty(cForests) Then
While Not cForests.EOF
Dim oRDSE
Dim oADObj
Set oRDSE = GetObject("LDAP://" &amp; cForests.Fields("cn").Value &amp; "/RootDSE")
If Not IsEmpty(oRDSE) Then
Set oADObj = new ADObject
oADObj.Init iType_Forest, iType_ADContainer, DNSNameFromDN(oRDSE.Get("defaultNamingContext")), oRDSE.Get("defaultNamingContext"), oADContainer, oRDSE
If Err &lt;&gt; 0 Then '//skip discovery for this forest and drop an event
CreateErrorEvent "Cannot discover forest: " &amp; cForests.Fields("cn").Value, oAPI
Else
oTempStack.Push(oADObj)
End If
End If
cForests.MoveNext
Wend
End If
While oTempStack.Count &gt; 0
oStack.Push(oTempStack.Pop())
Wend
Set oTempStack = Nothing
PrepareInitialStack = 0
End Function

'*************************************************************************
' LDAPQuery
' - Excutes LDAP query and returns the result as an object
'*************************************************************************
Function LDAPQuery(ByRef strPath, ByRef strFilter, ByRef strFields, ByRef strScope, ByRef oADOConn, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim oResult
Dim strQuery
strQuery = "&lt;LDAP://" &amp; strPath &amp;"&gt;;" &amp; strFilter &amp; ";" &amp; strFields &amp; ";" &amp; strScope
Set oResult = oADOConn.Execute(strQuery)
If Err &lt;&gt; 0 Then
CreateErrorEvent "LDAP query failed: " &amp; strQuery, oAPI
Set oResult = Nothing
End If
Set LDAPQuery = oResult
End Function

'*************************************************************************
' Explorer
' - DFS explorer
'*************************************************************************
Function Explorer(ByRef oStack, ByRef oDiscData, ByRef oADOConn, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim oADObj
Dim oChildStack
Dim ohtDC
Set ohtDC = CreateObject("System.Collections.Hashtable")
Set oChildStack = CreateObject("System.Collections.Stack")
If Err &lt;&gt; 0 Then
Explorer = 8
Exit Function
End If
While (oStack.Count &gt; 0)
Set oADObj = oStack.Pop()
iResult = Dispatcher(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
If iResult &lt;&gt; 0 Then
CreateErrorEvent iResult, oAPI
oChildStack.Clear()
Else
While (oChildStack.Count &gt; 0)
oStack.Push(oChildStack.Pop())
Wend
End If
Set oADObj = Nothing
Wend
Explorer = 0
End Function

'*************************************************************************
' Dispatcher
' - for each discovery on forest/site/sitelink/connectionobject/dccomputer
'*************************************************************************
Function Dispatcher(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
Dim iResult
Select Case oADObj.iType
Case iType_Forest
iResult = DiscoverForest(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
Case iType_Domain
iResult = DiscoverDomain(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
Case iType_SiteLink
iResult = DiscoverSiteLink(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
Case iType_Site
iResult = DiscoverSite(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
Case iType_DCComputer
iResult = DiscoverDCComputer(oADObj, oDiscData, oADOConn, oChildStack, ohtDC, oAPI)
End Select
If iResult &lt;&gt; 0 Then
Dispatcher = iResult
Exit Function
End If
Dispatcher = 0
End Function

Function GetDNSName(sPath)
Dim oNTDS, oServer
Set oNTDS = GetObject("LDAP://" &amp; sPath)
Set oServer = GetObject(oNTDS.Parent)
GetDNSName = LCase(oServer.Get("dNSHostName"))
End Function

Function DNSNameFromDN(sDN)
Dim sDNS
sDNS = Mid(sDN, 4)
sDNS = Replace(sDNS, ",DC=", ".")
DNSNameFromDN = LCase(sDNS)
End Function

'*************************************************************************
' DiscoverForest
' - called by Dispatcher for Forest discovery
'*************************************************************************
Function DiscoverForest(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim oRootDSE
Dim cSites
Dim cDomains
Dim cSiteLinks
Set oRootDSE = oADObj.oObject
ohtDC.Clear '//Clean previous forest DC hashtable
Dim arrParam(2)
arrParam(0) = GetDNSName(GetObject("LDAP://" &amp; oRootDSE.Get("schemaNamingContext")).Get("fSMORoleOwner"))
arrParam(1) = GetDNSName(GetObject("LDAP://CN=Partitions," &amp; oRootDSE.Get("configurationNamingContext")).Get("fSMORoleOwner"))
iResult = oADObj.CreateInstance(arrParam, oDiscData, NULL)
If iResult &lt;&gt; 0 Then
DiscoverForest = 9
Exit Function
End If

Dim arrDomainCols(4)
arrDomainCols(0) = "cn"
arrDomainCols(1) = "nCName"
arrDomainCols(2) = "trustParent"
arrDomainCols(3) = "distinguishedName"
Set cDomains = LDAPQuery(oADObj.strForestName &amp; "/" &amp; oRootDSE.Get("ConfigurationNamingContext"), "(&amp; (&amp; (objectCategory=crossRef) (systemflags=3)) (!trustParent=*))", "cn, nCName, distinguishedName, trustParent", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cDomains, arrDomainCols, oADObj, iType_Domain, iType_Forest, oChildStack)

Dim arrSiteLinkCols(7)
arrSiteLinkCols(0) = "cn"
arrSiteLinkCols(1) = "cost"
arrSiteLinkCols(2) = "siteList"
arrSiteLinkCols(3) = "replInterval"
arrSiteLinkCols(4) = "distinguishedName"
arrSiteLinkCols(5) = "schedule"
arrSiteLinkCols(6) = "isDeleted"
Set cSiteLinks = LDAPQuery(oADObj.strForestName &amp; "/CN=Inter-site Transports, CN=sites," &amp; oRootDSE.Get("ConfigurationNamingContext"), "(objectCategory=siteLink)" , "cn, cost, siteList, replInterval, distinguishedName, schedule, isDeleted", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cSiteLinks, arrSiteLinkCols, oADObj, iType_SiteLink, iType_Forest, oChildStack)

Dim arrSiteCols(3)
arrSiteCols(0) = "cn"
arrSiteCols(1) = "adspath"
arrSiteCols(2) = "distinguishedName"
Set cSites = LDAPQuery(oADObj.strForestName &amp; "/CN=Sites," &amp; oRootDSE.Get("ConfigurationNamingContext"), "(objectCategory=site)" , "cn, adspath, distinguishedName", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cSites, arrSiteCols, oADObj, iType_Site, iType_Forest, oChildStack)

DiscoverForest = 0
End Function

Function PrepareChild(ByRef cCollection, ByRef arrCols, ByRef oADObj,ByVal iType, ByVal iParentType, ByRef oChildStack)
If Not IsEmpty(cCollection) Then
While Not cCollection.EOF
Dim i
Dim oChild
Dim ohtChild
Set oChild = new ADObject
Set ohtChild = CreateObject("System.Collections.Hashtable")
For i=0 To UBound(arrCols) - 1
ohtChild.Add arrCols(i), cCollection.Fields(arrCols(i)).Value
Next
oChild.Init iType, iParentType, oADObj.strForestName, oADObj.strForestDN, oADObj.oInstance, ohtChild
oChildStack.Push(oChild)
cCollection.MoveNext
Wend
End If
PrepareChild = 0
End Function

'*************************************************************************
' DiscoverDomain
' - called by Dispatcher for Domain discovery
'*************************************************************************
Function DiscoverDomain(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim oDomain
Dim arrParam(6)

Dim arrDCCols(1)
Dim cDCComputers

Dim arrDomainCols(4)
Dim cDomains
Dim oDNC, sPDC, oRID, sRID, oInfra, sInfra

Set oDNC = GetObject("LDAP://" &amp; oADObj.oObject("nCName"))
sPDC = GetDNSName(oDNC.Get("fSMORoleOwner"))
Set oRID = GetObject("LDAP://CN=RID Manager$,CN=System," &amp; oADObj.oObject("nCName"))
sRID = GetDNSName(oRID.Get("fSMORoleOwner"))
Set oInfra = GetObject("LDAP://CN=Infrastructure," &amp; oADObj.oObject("nCName"))
sInfra = GetDNSName(oInfra.Get("fSMORoleOwner"))

arrParam(0) = DNSNameFromDN(oADObj.oObject("nCName")) '//Name
arrParam(1) = oADObj.oObject("nCName") '//Default NamingContext
arrParam(2) = GetDNSName(oDNC.Get("fSMORoleOwner")) '//PDC
arrParam(3) = sRID
arrParam(4) = sInfra
arrParam(5) = oADObj.oObject("trustParent")

iResult = oADObj.CreateInstance(arrParam, oDiscData, ohtDC)
If iResult &lt;&gt; 0 Then
DiscoverDomain = 10
Exit Function
End If

arrDomainCols(0) = "cn"
arrDomainCols(1) = "nCName"
arrDomainCols(2) = "trustParent"
arrDomainCols(3) = "distinguishedName"
Set cDomains = LDAPQuery(oADObj.strForestName &amp; "/CN=Configuration," &amp; oADObj.strForestDN, "(&amp; (&amp; (objectCategory=crossRef) (systemflags=3)) (trustParent=" &amp; oADObj.oObject("distinguishedName") &amp; "))" , "cn, nCName, distinguishedName, trustParent", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cDomains, arrDomainCols, oADObj, iType_Domain, iType_Domain, oChildStack)

arrDCCols(0) = "dNSHostName"
Set cDCComputers = LDAPQuery(DNSNameFromDN(oADObj.oObject("nCName")) &amp; "/OU=Domain Controllers," &amp; oADObj.oObject("nCName"), "(objectCategory=computer)", "dNSHostName", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cDCComputers, arrDCCols, oADObj, iType_DCComputer, iType_Domain, oChildStack)
DiscoverDomain = 0
End Function

'*************************************************************************
' DiscoverSiteLink
' - called by Dispatcher for SiteLink discovery
'*************************************************************************
Function DiscoverSiteLink(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim i
Dim arrParam(4)
arrParam(0) = oADObj.oObject("cn")
arrParam(1) = oADObj.oObject("replInterval")
If InStr(UCase(oADObj.oObject("distinguishedName")), "CN=IP") &gt; 0 Then
arrParam(2) = "IP"
Else
arrParam(2) = "SMTP"
End If
arrParam(3) = oADObj.oObject("cost")
iResult = oADObj.CreateInstance(arrParam, oDiscData, ohtDC)
If iResult &lt;&gt; 0 Then
DiscoverSiteLink = 11
Exit Function
End If

Dim arrSiteCols(3)
arrSiteCols(0) = "cn"
arrSiteCols(1) = "adspath"
arrSiteCols(2) = "distinguishedName"
For i=0 To UBound(oADObj.oObject("siteList"))
Dim cSites
Set cSites = LDAPQuery(oADObj.strForestName &amp; "/" &amp; oADObj.oObject("siteList")(i), "(objectCategory=site)" , "cn, adspath, distinguishedName", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cSites, arrSiteCols, oADObj, iType_Site, iType_SiteLink, oChildStack)
Next
End Function

'*************************************************************************
' DiscoverSite
' - called by Dispatcher for Site discovery
'*************************************************************************
Function DiscoverSite(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim cServers
Dim cSiteSettings
Dim arrParam(4) '//name, ISTGEnabled, ISTGRoleHolder, subnets
Dim arrDCCols(1) '//dNSHostName
arrParam(0) = oADObj.oObject("cn")
Set cSiteSettings = LDAPQuery(oADObj.oObject("distinguishedName"), "(interSiteTopologyGenerator=*)", "interSiteTopologyGenerator,options","subtree", oADOConn, oAPI)
If IsEmpty(cSiteSettings) Then '//If cSiteSettings is empty, then skip discovery for this site
DiscoverSite = 0
Exit Function
End If
If Not cSiteSettings.EOF Then
If cSiteSettings.Fields("options") AND 1 THEN
arrParam(1) = "No"
arrParam(2) = "None"
Else
arrParam(1) = "Yes"
Dim oISTG
Set oISTG = GetObject("LDAP://" &amp; cSiteSettings.Fields("interSiteTopologyGenerator") )
If Err &lt;&gt; 0 Then
arrParam(2) = "Unknown"
Else
Dim oISTGServer
Set oISTGServer = GetObject(oISTG.Parent)
arrParam(2) = oISTGServer.Get("CN")
End If
End If
Else
arrParam(1) = "No"
arrParam(2) = "None"
End If
arrParam(3) = DiscoverSubnets(oADObj.oObject("distinguishedName"), oADOConn, oAPI)

iResult = oADObj.CreateInstance(arrParam, oDiscData, ohtDC)
If iResult &lt;&gt; 0 Then
CreateErrorEvent 12, oAPI
DiscoverSite = 12
Exit Function
End If

arrDCCols(0) = "dNSHostName"
Set cServers = LDAPQuery(oADObj.strForestName &amp; "/" &amp; oADObj.oObject("distinguishedName"), "(objectCategory=Server)", "dNSHostName", "subtree", oADOConn, oAPI)
iResult = PrepareChild(cServers, arrDCCols, oADObj, iType_DCComputer, iType_Site, oChildStack)
DiscoverSite = 0
End Function

'*************************************************************************
' DiscoverSubnets
' - called Site discovery
' - This fills up subnet property of site class, but due to the string length
' constraint, we can only discover maximum of 12 subnets: floor(255/20)
'*************************************************************************
Function DiscoverSubnets(ByRef strSiteDN, ByRef oADOConn, ByRef oAPI)
Dim strSubnets
Dim iCount
Dim cSubnets
Set cSubnets = LDAPQuery(GetObject("LDAP://RootDSE").Get("configurationNamingContext"), "(&amp; (objectCategory=subnet) (siteObject=" &amp; strSiteDN &amp; "))", "cn", "subtree", oADOConn, oAPI)
iCount = 0
If IsEmpty(cSubnets) Then
DiscoverSubnets = 0
Exit Function
End If
While Not cSubnets.EOF And iCount &lt; 12
strSubnets = strSubnets &amp; cSubnets.Fields("cn").Value &amp; " "
iCount = iCount + 1
cSubnets.MoveNext
Wend
strSubnets = Trim(strSubnets)
DiscoverSubnets = strSubnets
End Function

'*************************************************************************
' DiscoverDCComputer
' - called by Dispatcher for DCComputer discovery
'*************************************************************************
Function DiscoverDCComputer(ByRef oADObj, ByRef oDiscData, ByRef oADOConn, ByRef oChildStack, ByRef ohtDC, ByRef oAPI)
On Error Resume Next
Err.Clear
Dim iResult
Dim arrParam(1)
Dim strDCName, i, bNameFound
arrParam(0) = LCase(oADObj.oObject("dNSHostName"))

If bDiscoverAgentOnly Then
strDCName = arrParam(0)
bNameFound = false

For i = 0 To UBound(aNames)
If aNames(i) = strDCName Then
bNameFound = true
i = UBound(aNames) ' This terminates the loop
End If
Next

If bNameFound = false Then
DiscoverDCComputer = 0
Exit Function
End If
End If

iResult = oADObj.CreateInstance(arrParam, oDiscData, ohtDC)
If iResult &lt;&gt; 0 Then
DiscoverDCComputer = 13
Exit Function
End If
DiscoverDCComputer = 0
End Function

'*************************************************************************
' CreateErrorEvent
'*************************************************************************
Sub CreateErrorEvent(ByVal eid, ByRef oAPI) '//eid can be just a string: in this case strMsg is set to the eid passed to this function
Dim strMsg
strMsg = GetErrorMessage(eid)
Call oAPI.LogScriptEvent(strScriptName, EVENT_ID_SCRIPT_ERROR, EVENT_TYPE_ERROR, strMsg)
End Sub

'*************************************************************************
' CreateInformationEvent
'*************************************************************************
Sub CreateInformationEvent(ByVal eid, ByVal strMsg, ByRef oAPI) '//eid can be just a string: in this case strMsg is set to the eid passed to this function
If bVerboseLogging Then
Call oAPI.LogScriptEvent(strScriptName, eid, EVENT_TYPE_INFORMATION, strMsg)
End If
End Sub

'*************************************************************************
' GetErrorMessage
'*************************************************************************
Function GetErrorMessage(ByVal eid)
Dim strMsg
Select Case eid
Case 2 strMsg = "Invalid number of parameters"
Case 3 strMsg = "Cannot create Discovery Data"
Case 4 strMsg = "Cannot create ADODB connection"
case 5 strMsg = "Cannot open connection to ADs Provider"
Case 6 strMsg = "Cannot create System.Collection.Stack"
Case 7 strMsg = "Cannot prepare RootDSEs for multiforest discovery, possibly did not enough permission to access RootDSE of other forests or failed to bind local RootDSE"
Case 8 strMsg = "Cannot prepare child stack in Explore()"
Case 9 strMsg = "Forest class instantiation failed"
Case 10 strMsg = "Domain class instantiation failed"
Case 11 strMsg = "SiteLink class instantiation failed"
Case 12 strMsg = "Site class instantiation failed"
Case 13 strMsg = "DC Computer class instantiation failed"
Case 14 strMsg = "As error occured while getting the list of agent names"
Case 15 strMsg = "The Operations Manager Installation path is empty"
Case 16 strMsg = "The Powershell path is empty"
Case Else strMsg = eid '// all other case, let error message be event id (it can handle actuall error message passed instead of eid)
End Select
GetErrorMessage = strMsg
End Function

'*************************************************************************
' GetAgentNames
' Description: Get the list of FQDNS of all agent-monitored computers
'*************************************************************************
Function GetAgentNames(ByVal strOpsMgrPath, ByVal strOpsMgrVersion, ByVal strPowershellPath, ByVal strManagementGroupName, ByRef oAPI)
On Error Resume Next
Dim strOutputFile, strErrrOutputFile, strOutput, strCmd, strGUID
Dim strCmdToUse, strOptionToUse, strFullCmd, strPS
Dim oTempFolder
Dim intMajorVersion

Set oShell = CreateObject("WScript.Shell")
If Err &lt;&gt; 0 Then
CreateErrorEvent "Cannot create the Wscript.Shell object", oAPI
GetAgentNames = null
Exit Function
End If

Set oFso = CreateObject("Scripting.FileSystemObject")
If Err &lt;&gt; 0 Then
CreateErrorEvent "Cannot create the Scripting.FileSystemObject object", oAPI
GetAgentNames = null
Exit Function
End If

Set oTempFolder = oFso.GetSpecialFolder(2) ' Temp Folder

strGUID = GetGUID()

strOutputFile = oTempFolder.Path &amp; "\" &amp; strScriptName &amp; "-Data-" &amp; strGUID &amp; ".txt"
strErrrOutputFile = oTempFolder.Path &amp; "\" &amp; strScriptName &amp; "-Error-" &amp; strGUID &amp; ".txt"

CreateInformationEvent EVENT_ID_DISCOVERY_INFO,"Operations Manager Version " &amp; strOpsMgrVersion &amp; " has been detected",oAPI

' The syntax of the strOpsMgrVersion is always of the form &lt;Major&gt;.&lt;Minor&gt;.&lt;Build&gt;.&lt;Revision&gt;
' Example: For Operations Manager 2012, the version is 7.0.8560.0
' The Left most character of the strOpsMgrVersion string always contains the Major version of the product
intMajorVersion = CInt(Left(strOpsMgrVersion,1))

' Determine the appropiate PowerShell cmdlet to be used to obtain the "Agent managed machines"
If intMajorVersion &lt; 7 then
' On SCOM versions older than 2012, in order to have access to the SCOM PowerShell cmdlets we must be running the Operations Manager Client Shell
strPS = QuoteWrap( _
".\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.Functions.ps1; " &amp; _
"Start-OperationsManagerClientShell -ManagementServerName: \""\"" -PersistConnection: $false -Interactive: $false; Get-Agent" &amp; _
" | where {$_.ManagementGroup -like \""" &amp; strManagementGroupName &amp; "\""} | Format-List Name")

strCmdToUse = "cd " &amp; QuoteWrap(strOpsMgrPath) &amp; " &amp; " &amp; QuoteWrap(strPowershellPath)

strOptionToUse = _
"-PSConsoleFile Microsoft.EnterpriseManagement.OperationsManager.ClientShell.Console.psc1 " &amp; _
"-command " &amp; strPS
Else
' Starting from SCOM 2012, the OperationsManager PowerShell module gives us access to SCOM management cmdlets
' that were previously available on the Operations Manager Client shell
strPS = QuoteWrap( _
"Import-Module OperationsManager; Get-SCOMAgent" &amp; _
" | where {$_.ManagementGroup -like \""" &amp; strManagementGroupName &amp; "\""} | Format-List Name")

' Note that in this case, since the default value for strPowershellPath contains the path for PowerShell V1.0, we don't want to use it
' Because that version does not support the Import-Module cmdlet, which is necessary for using the OperationsManager module.
' We use "Powershell.exe" without a path to let the system pick the most up to date version, which most likely will be newer tha V1.0
' and therefore, most likely to support the Import-Module cmdlet
strCmdToUse = "PowerShell.exe"

strOptionToUse = _
"-NoProfile -NonInteractive -Command " &amp; strPS
End If

strFullCmd = "cmd.exe /C " &amp; strCmdToUse &amp; " " &amp; strOptionToUse &amp; " &gt; " &amp; QuoteWrap(strOutputFile) &amp; " 2&gt; " &amp; QuoteWrap(strErrrOutputFile) &amp; " " &amp; """"
CreateInformationEvent EVENT_ID_DISCOVERY_INFO,"Executing Agent discovery command:" &amp; vbCrLf &amp; strFullCmd ,oAPI
strOutput = RunCmd(strFullCmd, strOutputFile, strErrrOutputFile, true)

Set oShell = Nothing

Dim aStrs, i, strThisName, strNewName, aResultsSize
Dim aResults()

aResultsSize = 0

aStrs = split(strOutput, "Name :")

For i = 0 to UBound(aStrs)
strThisName = aStrs(i)
strNewName = LCase(Replace(Trim(strThisName), Chr(13) &amp; Chr(10), ""))

If Len(strNewName) &lt;&gt; 0 Then
Redim Preserve aResults(aResultsSize + 1)
CreateInformationEvent EVENT_ID_DISCOVERY_INFO,"The discovery script has detected the Operations Manager agent on machine: " &amp; strNewName, oAPI
aResults(aResultsSize) = strNewName
aResultsSize = aResultsSize + 1
End If
Next

If aResultsSize = 0 Then
GetAgentNames = null
CreateInformationEvent EVENT_ID_DISCOVERY_INFO,"The Discovery script did not find any machines with the Operations Manager agent installed" , oAPI
Else
GetAgentNames = aResults
End If
End Function

'*************************************************************************
' RunCmd
' Description: Execute an exteranl command by creating a command propmpt
' and running that command in the command prompt
' Globals: oShell, fso
'*************************************************************************
Function RunCmd(CmdString,strOutputFile, strErrrOutputFile, boolGetOutPut)
On Error Resume Next
Dim oExec
Dim output
Dim strOutPut
Dim objFile1, objFile2
Dim strStdOut, strStdErr

oShell.Run CmdString, 0, boolGetOutPut

WScript.Sleep(5000)

'Get StdOut and StdErr
strStdOut = ""
strStdErr = ""

Set objFile1 = oFso.OpenTextFile(strOutputFile)
If Err &lt;&gt; 0 Then
CreateErrorEvent "Error opening output file: """ &amp; strOutputFile &amp; "", oAPI
Exit Function
End If

If Not(objFile1.AtEndOfStream) Then
strStdOut = objFile1.readAll()
End If
objFile1.close()
oFso.DeleteFile strOutputFile,true
Set objFile1 = Nothing

Set objFile2 = oFso.OpenTextFile(strErrrOutputFile)
If Err &lt;&gt; 0 Then
CreateErrorEvent "Error opening error file: """ &amp; strErrrOutputFile &amp; "", oAPI
Exit Function
End If

If Not(objFile2.AtEndOfStream) Then
strStdErr = objFile2.readAll()
End If
objFile2.close()
oFso.DeleteFile strErrrOutputFile,true
Set objFile2 = Nothing

If boolGetOutPut Then
strOutPut = strStdOut
Else
strOutPut = "1"
End If

If strStdErr &lt;&gt; "" Then
strOutPut = "Error: " &amp; strStdErr
End If

RunCmd = strOutPut
End Function

'*************************************************************************
' GetGUID
' Description: Create a random GUID
'*************************************************************************
Function GetGUID()
Dim TypeLib, tg
Set TypeLib = CreateObject("Scriptlet.TypeLib")
tg = TypeLib.Guid
Set TypeLib = Nothing
GetGUID = left(tg, len(tg)-2)
End Function

'*************************************************************************
' QuoteWrap
' Description: Wrap a string in quotes if not already wrapped
'*************************************************************************
Function QuoteWrap(myString)
If (myString &lt;&gt; "") And (left(mySTring,1) &lt;&gt; Chr(34)) And (Right(myString,1) &lt;&gt; Chr(34)) Then
QuoteWrap = Chr(34) &amp; myString &amp; Chr(34)
Else
QuoteWrap = myString
End If
End Function


'*************************************************************************
' Main
'*************************************************************************
Sub Main()
Dim oAPI
Dim oDiscData
Dim oStack
Dim oADOConn
Dim iResult
Dim dtStart
dtStart = Now

iResult = InitializeEnvironment(oAPI, oDiscData, oADOConn, oStack)
If iResult &lt;&gt; 0 Then
CreateErrorEvent iResult, oAPI
Exit Sub
End If
iResult = PrepareInitialStack(oADOConn, oStack, oDiscData, oAPI)
If iResult &lt;&gt; 0 Then
CreateErrorEvent iResult, oAPI
Exit Sub
End If
iResult = Explorer(oSTack, oDiscData, oADOConn, oAPI)
If iResult &lt;&gt; 0 Then
CreateErrorEvent iResult, oAPI
Exit Sub
End If

' If we have reached this section of the code, no critical errors have been found.
' Log an event to signal successful discovery of the AD Topology
CreateInformationEvent EVENT_ID_SUCCESS,"The script '" &amp; strScriptName &amp; "' completed successfully in " &amp; DateDiff("s", dtStart, Now) &amp; " second(s).", oAPI
oAPI.Return oDiscData
End Sub

Call Main()
</Script></Contents>
</File>
</Files>
</DataSource>
</Discovery>