Script de detección del clúster (con filtro de recursos)

Microsoft.Windows.Cluster.Monitoring.Discovery.ScriptProbe.WithResourceFilter (ProbeActionModuleType)

Módulo de detección de script para el clúster de servidores de Windows.

Element properties:

TypeProbeActionModuleType
IsolationAny
AccessibilityPublic
RunAsMicrosoft.Windows.Cluster.PrivilegedAccount
InputTypeSystem.BaseData
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Script ProbeAction Microsoft.Windows.ScriptDiscoveryProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
DiscoverUnusedNetworksbool$Config/DiscoverUnusedNetworks$Detectar redes no usadas
AppendClusterNameToResourceGroupNamebool$Config/AppendClusterNameToResourceGroupName$Anexar nombre del clúster al nombre del grupo de recursos
DiscoverCSVResourcesbool$Config/DiscoverCSVResources$Detectar recursos de volumen compartido de clúster
DiscoverNonCSVResourcesbool$Config/DiscoverNonCSVResources$Detectar recursos de clúster
ResourceGroupDiscoveryLimitint$Config/ResourceGroupDiscoveryLimit$Límite de detección de grupo de recursos
TimeoutSecondsint$Config/TimeoutSeconds$Tiempo de espera en segundos
ResourceGroupTypeFilterstring$Config/ResourceGroupTypeFilter$

Source Code:

<ProbeActionModuleType ID="Microsoft.Windows.Cluster.Monitoring.Discovery.ScriptProbe.WithResourceFilter" Accessibility="Public" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false" PassThrough="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="DiscoverySourceId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="DiscoverUnusedNetworks" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="NetworkContainsInterfaceGuid" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="NetworkInterfaceTypeGuid" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="NetworkInterfacePropClusterNameGuid" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="NetworkInterfacePropNameGuid" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="DiscoverCSVResources" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="DiscoverNonCSVResources" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ResourceGroupDiscoveryLimit" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="AppendClusterNameToResourceGroupName" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="NetworkInterfacePropClusterAdapterID" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="ResourceGroupTypeFilter" type="xsd:string"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="DiscoverUnusedNetworks" Selector="$Config/DiscoverUnusedNetworks$" ParameterType="bool"/>
<OverrideableParameter ID="AppendClusterNameToResourceGroupName" Selector="$Config/AppendClusterNameToResourceGroupName$" ParameterType="bool"/>
<OverrideableParameter ID="DiscoverCSVResources" Selector="$Config/DiscoverCSVResources$" ParameterType="bool"/>
<OverrideableParameter ID="DiscoverNonCSVResources" Selector="$Config/DiscoverNonCSVResources$" ParameterType="bool"/>
<OverrideableParameter ID="ResourceGroupDiscoveryLimit" Selector="$Config/ResourceGroupDiscoveryLimit$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="ResourceGroupTypeFilter" Selector="$Config/ResourceGroupTypeFilter$" ParameterType="string"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptDiscoveryProbe">
<ScriptName>DiscoverClustering.vbs</ScriptName>
<Arguments>$Config/DiscoverySourceId$ $Target/Id$ $Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$ $Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/NetbiosComputerName$ $Config/DiscoverUnusedNetworks$ $Config/NetworkContainsInterfaceGuid$ $Config/NetworkInterfaceTypeGuid$ $Config/NetworkInterfacePropClusterNameGuid$ $Config/NetworkInterfacePropNameGuid$ $Config/DiscoverCSVResources$ $Config/DiscoverNonCSVResources$ $Config/ResourceGroupDiscoveryLimit$ $Config/AppendClusterNameToResourceGroupName$ $Config/NetworkInterfacePropClusterAdapterID$ "$Config/ResourceGroupTypeFilter$"</Arguments>
<ScriptBody><Script>'Copyright (c) Microsoft Corporation. All rights reserved.
Option Explicit

SetLocale("en-us")

Const wbemCimtypeUseDefault = 0 'Use Default Type CIM type - Custom
Const wbemCimtypeSint16 = 2 'Signed 16-bit integer
Const wbemCimtypeSint32 = 3 'Signed 32-bit integer
Const wbemCimtypeReal32 = 4 '32-bit real number
Const wbemCimtypeReal64 = 5 '64-bit real number
Const wbemCimtypeString = 8 'String
Const wbemCimtypeBoolean = 11 'Boolean value
Const wbemCimtypeObject = 13 'CIM object
Const wbemCimtypeSint8 = 16 'Signed 8-bit integer
Const wbemCimtypeUint8 = 17 'Unsigned 8-bit integer
Const wbemCimtypeUint16 = 18 'Unsigned 16-bit integer
Const wbemCimtypeUint32 = 19 'Unsigned 32-bit integer
Const wbemCimtypeSint64 = 20 'Signed 64-bit integer
Const wbemCimtypeUint64 = 21 'Unsigned 64-bit integer
Const wbemCimtypeDatetime = 101 'Date/time value
Const wbemCimtypeReference = 102 'Reference to a CIM object
Const wbemCimtypeChar16 = 103 '16-bit character

Const ErrAction_None = 0
Const ErrAction_Trace = 1
Const ErrAction_ThrowError = 16
Const ErrAction_Abort = 32
Const ErrAction_ThrowErrorAndAbort = 48

Const WIN_SRV_2012_OSVer = "6.2"
Const WIN_SRV_2012R2_OSVer = "6.3"
Const DefaultClusterGroupTypes = ""


Dim g_oUtil
Set g_oUtil = New Util

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_NONE)

Dim g_oClusterUtil
Set g_oClusterUtil = new ClusterUtil

Dim oArgs
Set oArgs = WScript.Arguments

If oArgs.Count &lt; 12 Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Need to provide arguments"

Wscript.Quit -1
End If

'==========================================================================
' Initialize the arguments in VBScript
'==========================================================================

Dim SourceId, ManagedEntityId, HealthServiceName, NetBiosName

SourceId = oArgs(0) ' this is always going to be same GUID to allow for multiple discoveries do updates at the same time
ManagedEntityId = oArgs(1)
HealthServiceName = oArgs(2)
NetBiosName = oArgs(3)

Dim discoverUnusedNetworks
discoverUnusedNetworks = CBool(oArgs(4))

Dim networkContainsInterfaceGuid
networkContainsInterfaceGuid = oArgs(5)

Dim networkInterfaceTypeGuid
networkInterfaceTypeGuid = oArgs(6)
Dim networkInterfacePropClusterNameGuid
networkInterfacePropClusterNameGuid = oArgs(7)
Dim networkInterfacePropNameGuid
networkInterfacePropNameGuid = oArgs(8)

Dim discoverCSVResources
discoverCSVResources = CBool(oArgs(9))
Dim discoverNonCSVResources
discoverNonCSVResources = CBool(oArgs(10))
Dim ResourceGroupDiscoveryLimit
ResourceGroupDiscoveryLimit = CInt(oArgs(11))

Dim appendClusterNameToResourceGroupName

If oArgs.Count = 12 Then
appendClusterNameToResourceGroupName = false
ElseIf oArgs.Count &gt; 12 And ( IsEmpty(oArgs(12)) or IsNull(oArgs(12)) or Len(oArgs(12)) = 0 )Then
appendClusterNameToResourceGroupName = false
Else
appendClusterNameToResourceGroupName = CBool(oArgs(12))
End If

Dim strNetworkInterfacePropClusterAdapterID

If oArgs.Count = 13 Then
strNetworkInterfacePropClusterAdapterID = ""
ElseIf oArgs.Count &gt; 13 And ( IsEmpty(oArgs(13)) or IsNull(oArgs(13)) or Len(oArgs(13)) = 0 )Then
strNetworkInterfacePropClusterAdapterID = ""
Else
strNetworkInterfacePropClusterAdapterID = oArgs(13)
End If

'Adding New Parameter for Resource Group Types Filter
Dim strResourceGroupTypeFilter, ObjResourceGroupTypeFilter

If oArgs.Count = 14 Then
strResourceGroupTypeFilter = DefaultClusterGroupTypes
ElseIf oArgs.Count &gt; 14 And ( IsEmpty(oArgs(14)) or IsNull(oArgs(14)) or Len(oArgs(14)) = 0 )Then
strResourceGroupTypeFilter = DefaultClusterGroupTypes
Else
strResourceGroupTypeFilter = oArgs(14)
End If

ObjResourceGroupTypeFilter = Split(strResourceGroupTypeFilter , ",")

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"SourceId : " &amp; SourceId
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"ManagedEntityId : " &amp; ManagedEntityId
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"HealthServiceName : " &amp; HealthServiceName

'==========================================================================
' Main
'==========================================================================

Dim oAPI
Set oAPI = CreateObject("MOM.ScriptAPI")
If oAPI is Nothing Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed to get Discovery API. MOM v3 must be installed to execute this script"

if 0 &lt;&gt; Err.number then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed with error " &amp; Err.number &amp; " - " &amp; Err.Description
end if
End If

Call DiscoverInstances()


'******************************************************************************
' FUNCTION: IndexOf
' DESCRIPTION: Returns Index of Search Element Value Inside an Array
' RETURNS: Index Number if not found return -1
'******************************************************************************
Function IndexOf(ByVal ObjArr, ByVal strToMatch)

'Default to an error code
IndexOf = -1

'Make sure an array was passed
If Not IsArray(ObjArr) Then Exit Function

'Check for matching index
Dim itmElem
For itmElem = 0 To UBound(ObjArr)
If StrComp(strToMatch, ObjArr(itmElem), vbTextCompare) = 0 Then
IndexOf = itmElem
Exit For
End If
Next

End Function

'******************************************************************************
' FUNCTION: GetRegistryKeyValue
' DESCRIPTION: Returns the Registry Key Value
' RETURNS: Registry Key Value
'******************************************************************************
Function GetRegistryKeyValue(ByVal keyPath, ByVal key)
Dim oReg, strKeyValue

Set oReg = CreateObject("WScript.Shell")
On Error Resume Next

strKeyValue = oReg.RegRead(keyPath &amp; key)
If Err.Number &lt;&gt; 0 Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"An error occurred while reading the registry: '" &amp; keyPath &amp; key &amp; "' Error Number: " &amp; Err.number &amp; " - " &amp; Err.Description
strKeyValue = ""
End If

' resume error
On Error Goto 0

GetRegistryKeyValue = strKeyValue
End Function

'******************************************************************************
' FUNCTION: CheckByOSCurrentVersion
' DESCRIPTION: Returns True if the Registry Key for CurrentVersion
' is equal the target OS Versions Number.
' RETURNS: Boolean: True, if build is greater or equal than the given number
'******************************************************************************
Private Function CheckByOSCurrentVersion() 'As Boolean
Dim strCurrentOSVer

strCurrentOSVer = GetRegistryKeyValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentVersion")

Select Case strCurrentOSVer
Case WIN_SRV_2012_OSVer
CheckByOSCurrentVersion = True
Case WIN_SRV_2012R2_OSVer
CheckByOSCurrentVersion = True
Case Else
CheckByOSCurrentVersion = False
End Select

End Function

'==========================================================================
' FUNCTIONS
'==========================================================================
Sub ThrowEmptyDiscoveryData(IsSnapShot)
Dim oDiscoveryDataTmp
set oDiscoveryDataTmp = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
oDiscoveryDataTmp.IsSnapshot = IsSnapShot

Call oAPI.Return(oDiscoveryDataTmp)
End Sub

Sub DiscoverInstances()
Dim boolUseWIN2012
boolUseWIN2012 = CheckByOSCurrentVersion()

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Started dicovery at machine local time: " &amp; CStr(Time)

Dim oDiscoveryData
Set oDiscoveryData = oAPI.CreateDiscoveryData ( _
0, _
SourceId, _
ManagedEntityId _
)

If oDiscoveryData is Nothing Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed to get Discovery Data Object. MOM v3 must be installed to execute this script"

if 0 &lt;&gt; Err.number then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed with error " &amp; Err.number &amp; " - " &amp; Err.Description
end if

Exit Sub
End If

Dim winCluster
Set winCluster = New WinCluster

Call winCluster.Discover ( oDiscoveryData, boolUseWIN2012 )
Call oAPI.Return(oDiscoveryData)

g_oUtil.LogMessageNewLine _
g_oUtil.DBG_TRACE, _
"Finished dicovery at machine local time: " &amp; CStr(Time)

End Sub

'==========================================================================
' Class: WinClusterObject
' Description: base holding object and its properties
'==========================================================================
Class WinClusterObject

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal hostKey, _
ByRef oObject, _
ByVal discoveryClass, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for " &amp; discoveryClass &amp; "."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
discoveryClass _
)

With oInstance

Dim name
name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

If discoveryClass = "$MPElement[Name='Microsoft.Windows.Cluster.Group']$" And appendClusterNameToResourceGroupName = True Then
.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
name &amp; " (" &amp; hostKey &amp; ")"
Else
.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
name
End If

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", _
hostKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", _
Trim(name)

'Dim state
'state = g_oClusterUtil.WMIGetProperty ( oObject, "State", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
'
'.AddProperty _
' wrap with $...$ when ObjectState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectState", _
' state

End With

Set DiscoverInstance = oInstance

End Function

End Class ' WinClusterObject

'==========================================================================
' Class: WinCluster
' Description: holding cluster object and its properties
'==========================================================================
Class WinCluster

Private oClusters

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
Set oClusters = g_oClusterUtil.WMIGetInstances("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "MSCluster_Cluster")
End Sub

'==========================================================================
' Discover cluster classes
'==========================================================================
Public Sub Discover( _
ByRef oDiscoveryData, ByRef boolUseWIN2012 _
)

Dim oCluster
For Each oCluster in oClusters
Dim oClusterInstance
Set oClusterInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Cluster!Microsoft.Windows.Cluster']$" _
)

With oClusterInstance
.AddProperty _
"$MPElement[Name='Cluster!Microsoft.Windows.Cluster']/Name$", _
oCluster.Name
End With

' need to make sure that cluster was discovered as it is used in some relationships
oDiscoveryData.AddInstance(oClusterInstance)

' cluster node helpers
Dim winClusterNode
Set winClusterNode = new WinClusterNode

' nodes
Dim oNodes
Set oNodes = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_ClusterToNode where Antecedent = ""MSCluster_Cluster.Name=\""" &amp; oCluster.Name &amp; "\""""")

Dim oNode
For Each oNode in oNodes
Dim oRealNode
Set oRealNode = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", oNode.Dependent)

Dim oNodeInstance
Set oNodeInstance = winClusterNode.DiscoverInstance ( _
oCluster.Name, _
oRealNode, _
oDiscoveryData _
)

If Not oNodeInstance Is Nothing Then
winClusterNode.DiscoverClusterContainsRelationship _
oClusterInstance, _
oDiscoveryData
End If
Next

' networks
Dim oNetworks
Set oNetworks = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_ClusterToNetwork where GroupComponent = ""MSCluster_Cluster.Name=\""" &amp; oCluster.Name &amp; "\""""")

Dim oNetwork
For Each oNetwork in oNetworks
Dim oRealNetwork
Set oRealNetwork = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", oNetwork.PartComponent)

' cluster network helpers
Dim winClusterNetwork
Set winClusterNetwork = new WinClusterNetwork

Dim oNetworkInstance
Set oNetworkInstance = winClusterNetwork.DiscoverInstance ( _
oCluster.Name, _
oRealNetwork, _
oDiscoveryData, _
boolUseWIN2012 _
)

If Not oNetworkInstance Is Nothing Then
winClusterNetwork.DiscoverClusterContainsRelationship _
oClusterInstance, _
oCluster.Name, _
oRealNetwork.Name, _
oDiscoveryData
End If
Next

' cluster group helpers
Dim winClusterGroup
Set winClusterGroup = new WinClusterGroup

' groups
Dim oGroups
Set oGroups = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_ClusterToResourceGroup where GroupComponent = ""MSCluster_Cluster.Name=\""" &amp; oCluster.Name &amp; "\""""")

Dim oGroup
Dim iGroupCounter
iGroupCounter = 0


For Each oGroup in oGroups
Dim oRealGroup
Set oRealGroup = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", oGroup.PartComponent)

Dim autoFailbackType
Dim description
Dim failbackWindowEnd
Dim failbackWindowStart
Dim failoverPeriod
Dim failoverThreshold
Dim persistentState
Dim GroupType

autoFailbackType = g_oClusterUtil.WMIGetProperty ( oRealGroup, "AutoFailbackType", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
description = g_oClusterUtil.WMIGetProperty ( oRealGroup, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
failbackWindowEnd = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailbackWindowEnd", wbemCimtypeSint32, ErrAction_ThrowErrorAndAbort )
failbackWindowStart = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailbackWindowStart", wbemCimtypeSint32, ErrAction_ThrowErrorAndAbort )
failoverPeriod = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailoverPeriod", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
failoverThreshold = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailoverThreshold", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
persistentState = g_oClusterUtil.WMIGetProperty ( oRealGroup, "PersistentState", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )


'Apply Filter if Any
GroupType = g_oClusterUtil.WMIGetProperty ( oRealGroup, "GroupType", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
If IndexOf(ObjResourceGroupTypeFilter,GroupType) = -1 Then

'Getting Discovered Group Index for comparing it with defined Discovery Limit
iGroupCounter = iGroupCounter + 1

' resource group discover limit exceeded?
If iGroupCounter &gt; ResourceGroupDiscoveryLimit then
' yes
' log to event log
oAPI.LogScriptEvent "DiscoverClustering.vbs", 7010, 1, (HealthServiceName &amp; " hosts " &amp; iGroupCounter &amp; " resource groups which exceeds the configured threshold of " &amp; ResourceGroupDiscoveryLimit &amp; ".")
else
' no
' proceed with normal discovery


' undefined is empty string
If failbackWindowEnd = "-1" Then failbackWindowEnd = ""
If failbackWindowStart = "-1" Then failbackWindowStart = ""

Dim oGroupInstance
Set oGroupInstance = winClusterGroup.DiscoverInstance ( _
oCluster.Name, _
oRealGroup, _
autoFailbackType, _
description, _
failbackWindowEnd, _
failbackWindowStart, _
failoverPeriod, _
failoverThreshold, _
persistentState, _
oDiscoveryData _
)

'cluster contains groups
If Not oGroupInstance Is Nothing Then
winClusterGroup.DiscoverClusterContainsRelationship _
oClusterInstance, _
oCluster.Name, _
Trim(oRealGroup.Name), _
oDiscoveryData
End If

Dim oHostedGroupInstance
Set oHostedGroupInstance = winClusterGroup.DiscoverInstanceForHosted ( _
oCluster.Name, _
oRealGroup, _
autoFailbackType, _
description, _
failbackWindowEnd, _
failbackWindowStart, _
failoverPeriod, _
failoverThreshold, _
persistentState, _
oDiscoveryData _
)

' group contains hosted group
winClusterGroup.DiscoverClusterGroupContainsRelationship _
oCluster.Name, _
Trim(oRealGroup.Name), _
oDiscoveryData
end if
end if
Next

Next

End Sub

End Class ' WinCluster

'==========================================================================
' Class: WinClusterNode
' Description: holding cluster node and its properties
'==========================================================================
Class WinClusterNode

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal hostKey, _
ByRef oObject, _
ByRef oDiscoveryData _
)

'======================================================================
' only on same computer
'======================================================================

Dim name
Dim description
Dim buildNumber
Dim cSDVersion
Dim majorVersion
Dim minorVersion
Dim nodeHighestVersion
Dim nodeLowestVersion

name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
buildNumber = g_oClusterUtil.WMIGetProperty ( oObject, "BuildNumber", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
cSDVersion = g_oClusterUtil.WMIGetProperty ( oObject, "CSDVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
majorVersion = g_oClusterUtil.WMIGetProperty ( oObject, "MajorVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
minorVersion = g_oClusterUtil.WMIGetProperty ( oObject, "MinorVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
nodeHighestVersion = g_oClusterUtil.WMIGetProperty ( oObject, "NodeHighestVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
nodeLowestVersion = g_oClusterUtil.WMIGetProperty ( oObject, "NodeLowestVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )

If StrComp ( LCase(NetBiosName) , LCase(oObject.Name) ) = 0 Then

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for Microsoft.Windows.Cluster.Node."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/ClusterName$", _
hostKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeName$", _
Trim(name)

'Dim state
'state = g_oClusterUtil.WMIGetProperty ( oObject, "State", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
'
'.AddProperty _
' wrap with $...$ when NodeState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeState", _
' state

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/Description$", _
description

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/BuildNumber$", _
buildNumber

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/CSDVersion$", _
cSDVersion

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/MajorVersion$", _
majorVersion

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/MinorVersion$", _
minorVersion

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeHighestVersion$", _
nodeHighestVersion

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeLowestVersion$", _
nodeLowestVersion

'Dim enableEventLogReplication
'enableEventLogReplication = g_oClusterUtil.WMIGetProperty ( oObject, "EnableEventLogReplication", wbemCimtypeBoolean, ErrAction_None )
'
'.AddProperty _
' wrap with $...$ when NodeState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Node']/EnableEventLogReplication", _
' enableEventLogReplication

End With

Call oDiscoveryData.AddInstance(oInstance)
Set DiscoverInstance = oInstance

Call DiscoverClusterNodeHostsNodeRoleRelationship ( _
hostKey, _
oObject, _
oDiscoveryData _
)

Exit Function

End If

Set DiscoverInstance = Nothing

End Function

'==========================================================================
' Discover node hostinging role relationship instance
'==========================================================================
Private Sub DiscoverClusterNodeHostsNodeRoleRelationship( _
ByVal hostKey, _
ByRef oObject, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for node hosting roles."

Dim oNodeRoleInstance
Set oNodeRoleInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.NodeRole']$" _
)

With oNodeRoleInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

End With

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

End With

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Windows!Microsoft.Windows.ComputerHostsComputerRole']$" _
)

oRelationshipInstance.Source = oInstance
oRelationshipInstance.Target = oNodeRoleInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)

With oNodeRoleInstance

.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
oObject.Name

End With

Call oDiscoveryData.AddInstance(oNodeRoleInstance)

End Sub

'==========================================================================
' Discover cluster contains relationship instance
'==========================================================================
Public Sub DiscoverClusterContainsRelationship( _
ByRef oClusterInstance, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains nodes."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Node']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

End With

g_oClusterUtil.DiscoverClusterContainsRelationship _
oClusterInstance, _
oInstance, _
"$MPElement[Name='Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Node']$", _
oDiscoveryData

End Sub

End Class ' WinClusterNode

'==========================================================================
' Class: WinClusterNetwork
' Description: holding cluster network and its properties
'==========================================================================
Class WinClusterNetwork

Private roleNone

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
roleNone = False
End Sub

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal hostKey, _
ByRef oObject, _
ByRef oDiscoveryData, _
ByRef boolUseWIN2012 _
)

Dim clusterHelper
Set clusterHelper = new WinClusterObject

Dim oInstance
Set oInstance = clusterHelper.DiscoverInstance ( _
hostKey, _
oObject, _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']$", _
oDiscoveryData _
)

Dim address
Dim addressMask
Dim role
Dim description

address = g_oClusterUtil.WMIGetProperty ( oObject, "Address", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
addressMask = g_oClusterUtil.WMIGetProperty ( oObject, "AddressMask", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
role = g_oClusterUtil.WMIGetProperty ( oObject, "Role", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

If role = "0" Then
roleNone = True
End If

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']/Address$", _
address

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']/AddressMask$", _
addressMask

'.AddProperty _
' wrap with $...$ when Role is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Network']/Role", _
' role

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']/Description$", _
description

End With

Dim discoverNetwork
discoverNetwork = True

If discoverUnusedNetworks = False Then
If roleNone = True Then
discoverNetwork = False
End If
End If

If discoverNetwork = True Then
Call oDiscoveryData.AddInstance(oInstance)
Set DiscoverInstance = oInstance

Dim name
name = oObject.Name

'====================================================
' discover contains network interfaces
'====================================================

Dim oNetworkItfs
Set oNetworkItfs = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_NetworkToNetworkInterface where GroupComponent = ""MSCluster_Network.Name=\""" &amp; name &amp; "\""""")

Dim oNetworkItf
For Each oNetworkItf in oNetworkItfs
Dim oRealNetworkItf
Set oRealNetworkItf = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", oNetworkItf.PartComponent)

Dim e
Set e = New Error
On Error Resume Next

Dim winClusterNetworkInterface
Set winClusterNetworkInterface = new WinClusterNetworkInterface

e.Save
On Error Goto 0

If g_oClusterUtil.IsValidObject ( winClusterNetworkInterface ) = False Then
g_oUtil.ThrowScriptError "Unable to create network interface helper.", e
End If

Dim strs
strs = Split ( oRealNetworkItf.DeviceID, " - ", -1, 1 )

Dim baseOSItfName
If StrComp ( LCase(strs(1)) , LCase(oRealNetworkItf.SystemName) ) = 0 Then
baseOSItfName = strs(0)
Else
baseOSItfName = strs(1)
End If

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Network: " &amp; name &amp; " interface: " &amp; baseOSItfName

Call winClusterNetworkInterface.Initialize ( baseOSItfName )

Dim oNetworkItfInstance
Set oNetworkItfInstance = winClusterNetworkInterface.DiscoverInstance ( _
hostKey, _
baseOSItfName, _
oRealNetworkItf, _
oDiscoveryData, _
boolUseWIN2012 _
)

' discover that network contains interfaces
Call DiscoverContainsNetworkInterfacesRelationship ( _
hostKey, _
name, _
winClusterNetworkInterface.deviceID, _
oRealNetworkItf, _
oDiscoveryData _
)

Next

Else
Set DiscoverInstance = Nothing
End If
End Function

'==========================================================================
' Discover cluster containing network interfaces relationship instance
'==========================================================================
Private Sub DiscoverContainsNetworkInterfacesRelationship( _
ByVal hostKey, _
ByVal networkKey, _
ByVal networkItfKey, _
ByRef oRealNetworkItf, _
ByRef oDiscoveryData _
)

If StrComp ( LCase(NetBiosName) , LCase(oRealNetworkItf.SystemName) ) = 0 Then

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster network contains network interfaces."

Dim oNetworkInstance
Set oNetworkInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']$" _
)

With oNetworkInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", _
hostKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", _
networkKey

End With

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
NetworkInterfaceTypeGuid _
)

With oInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", _
networkItfKey

End With

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
NetworkContainsInterfaceGuid _
)

oRelationshipInstance.Source = oNetworkInstance
oRelationshipInstance.Target = oInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)

End If

End Sub

'==========================================================================
' Discover cluster contains relationship instance
'==========================================================================
Public Sub DiscoverClusterContainsRelationship( _
ByRef oClusterInstance, _
ByVal hostKey, _
ByVal networkKey, _
ByRef oDiscoveryData _
)

If roleNone = False Then
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains network."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Network']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", _
hostKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", _
networkKey

End With

g_oClusterUtil.DiscoverClusterContainsRelationship _
oClusterInstance, _
oInstance, _
"$MPElement[Name='Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Network']$", _
oDiscoveryData
End If
End Sub

End Class ' WinClusterNetwork

'==========================================================================
' Class: WinClusterNetworkInterface
' Description: holding cluster network interface its properties
'==========================================================================
Class WinClusterNetworkInterface

Public deviceID
Public adapterType
Public index
Public manufacturer
Public macAddress
Public serviceName

'======================================================================
' Method: Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Public Sub Initialize( ByVal NetworkName )
deviceID = ""
adapterType = ""
index = ""
manufacturer = ""
macAddress = ""
serviceName = ""

Dim WMISet, owObj, owObj2, oInstance, sDeviceID
If discoverUnusedNetworks= False Then
Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" &amp; NetworkName &amp; "' And NetConnectionStatus &lt;&gt; 0")
Else
Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" &amp; NetworkName &amp; "'")
End If

For Each owObj In WMISet
deviceID = g_oClusterUtil.WMIGetProperty(owObj, "DeviceID", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
adapterType = g_oClusterUtil.WMIGetProperty(owObj, "AdapterType", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
index = g_oClusterUtil.WMIGetProperty(owObj, "Index", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
manufacturer = g_oClusterUtil.WMIGetProperty(owObj, "Manufacturer", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
macAddress = g_oClusterUtil.WMIGetProperty(owObj, "MACAddress", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

' replaces colons in MAC with dashes to comply with IEEE 802 and NASM
macAddress = Replace(macAddress, ":", "-")

serviceName = g_oClusterUtil.WMIGetProperty(owObj, "ServiceName", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
Next
End Sub

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal clusterKey, _
ByVal networkItfKey, _
ByRef oObject, _
ByRef oDiscoveryData, _
ByRef boolUseWIN2012 _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for " &amp; networkInterfaceTypeGuid

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
networkInterfaceTypeGuid _
)

With oInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", _
deviceID

Dim adapter
Dim address
Dim description
Dim name
Dim strClusterAdapterID

adapter = g_oClusterUtil.WMIGetProperty ( oObject, "Adapter", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
address = g_oClusterUtil.WMIGetProperty ( oObject, "Address", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
name = g_oClusterUtil.WMIGetProperty ( oObject, "DeviceID", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
networkItfKey

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Name$", _
adapter

If description = "" Then
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
adapter
Else
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
description
End If

.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/IPAddress$", _
address

.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/AdapterType$", _
adapterType
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Index$", _
index
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Manufacturer$", _
manufacturer
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/MACAddress$", _
macAddress
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/ServiceName$", _
serviceName

.AddProperty _
networkInterfacePropClusterNameGuid, _
clusterKey
.AddProperty _
networkInterfacePropNameGuid, _
name

If boolUseWIN2012 = true Then
strClusterAdapterID = g_oClusterUtil.WMIGetProperty ( oObject, "AdapterId", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
strClusterAdapterID = Replace(strClusterAdapterID, "{", "")
strClusterAdapterID = Replace(strClusterAdapterID, "}", "")

.AddProperty _
strNetworkInterfacePropClusterAdapterID, _
strClusterAdapterID
End If


End With

Call oDiscoveryData.AddInstance(oInstance)
Set DiscoverInstance = oInstance

End Function

End Class ' WinClusterNetworkInterface

'========='==========================================================================
' Class: WinClusterGroup
' Description: holding group object and its properties
'==========================================================================
Class WinClusterGroup

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal hostKey, _
ByRef oObject, _
ByVal autoFailbackType, _
ByVal description, _
ByVal failbackWindowEnd, _
ByVal failbackWindowStart, _
ByVal failoverPeriod, _
ByVal failoverThreshold, _
ByVal persistentState, _
ByRef oDiscoveryData _
)

' instance

Dim clusterHelper
Set clusterHelper = new WinClusterObject

Dim oInstance
Set oInstance = clusterHelper.DiscoverInstance ( _
hostKey, _
oObject, _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']$", _
oDiscoveryData _
)

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/OriginalGroupName$", _
oObject.Name
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/AutoFailbackType$", _
autoFailbackType
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/Description$", _
description
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailbackWindowEnd$", _
failbackWindowEnd
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailbackWindowStart$", _
failbackWindowStart
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailoverPeriod$", _
failoverPeriod
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailoverThreshold$", _
failoverThreshold
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/PersistentState$", _
persistentState

Dim e
Set e = New Error
On Error Resume Next

Dim oService
Set oService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &amp; HealthServiceName &amp; "\root\mscluster")

e.Save
On Error Goto 0
If IsEmpty(oService) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Fail to connect to WMI.", e
End If
On Error Resume Next

Dim oActiveNode
Set oActiveNode = oService.ExecQuery("select * from MSCluster_NodeToActiveGroup where PartComponent = ""MSCluster_ResourceGroup.Name=\""" &amp; g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) &amp; "\""""")

e.Save
On Error Goto 0
If IsEmpty(oActiveNode) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query for active node returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

If Not oActiveNode Is Null Then
Dim oNode
For Each oNode in oActiveNode

Dim oActive
Set oActive = oService.Get(oNode.GroupComponent)

e.Save
On Error Goto 0
If IsNull(oActive) Then
g_oUtil.ThrowScriptError "Do not get a Node. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$", _
oActive.Name

Next
Else
' need to use current node

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$", _
NetBiosName

End If

End With

Call oDiscoveryData.AddInstance(oInstance)
Set DiscoverInstance = oInstance

'====================================================
' discover resources
'====================================================

Dim oResources
Set oResources = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_ResourceGroupToResource where GroupComponent = ""MSCluster_ResourceGroup.Name=\""" &amp; g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) &amp; "\""""")

Dim oResource
For Each oResource in oResources
Dim oRealResource
Set oRealResource = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", oResource.PartComponent)

' discovery enabled?
if discoverNonCSVResources then
' yes
Dim winClusterResource
Set winClusterResource = new WinClusterResource

Dim oResourceInstance
Set oResourceInstance = winClusterResource.DiscoverInstance ( _
hostKey, _
Trim(oObject.Name), _
oRealResource, _
oDiscoveryData _
)

' discover that group hosts this resource
Call winClusterResource.DiscoverClusterGroupHostsResourcesRelationship ( _
hostKey, _
Trim(oObject.Name), _
Trim(oRealResource.Name), _
oDiscoveryData _
)
end if
Next

' cluster shared volume discovery enabled and available storage group?
dim resourceGroupType
resourceGroupType = CLng(oObject.ExecMethod_("GetGroupType").ReturnValue)
if discoverCSVResources and resourceGroupType = 2 then
dim oClusterSharedVolumes
set oClusterSharedVolumes = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName &amp; "\root\mscluster", "select * from MSCluster_Resource where IsClusterSharedVolume = true" )

dim oCSV
for each oCSV in oClusterSharedVolumes

dim winCSVResource
Set winCSVResource = new WinClusterResource

dim oCSVInstance
set oCSVInstance = winCSVResource.DiscoverInstance ( _
hostKey, _
Trim(oObject.Name), _
oCSV, _
oDiscoveryData _
)

call winCSVResource.DiscoverClusterGroupHostsResourcesRelationship ( _
hostKey, _
Trim(oObject.Name), _
Trim(oCSV.Name), _
oDiscoveryData _
)
next
end if
End Function

'==========================================================================
' Discover cluster contains relationship instance
'==========================================================================
Public Sub DiscoverClusterContainsRelationship( _
ByRef oClusterInstance, _
ByVal hostKey, _
ByVal groupKey, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains groups."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", _
hostKey
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", _
Trim(groupKey)

End With

g_oClusterUtil.DiscoverClusterContainsRelationship _
oClusterInstance, _
oInstance, _
"$MPElement[Name='Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Group']$", _
oDiscoveryData

End Sub

'==========================================================================
' Discover cluster node hosted group
'==========================================================================
Public Function DiscoverInstanceForHosted( _
ByVal hostKey, _
ByRef oObject, _
ByVal autoFailbackType, _
ByVal description, _
ByVal failbackWindowEnd, _
ByVal failbackWindowStart, _
ByVal failoverPeriod, _
ByVal failoverThreshold, _
ByVal persistentState, _
ByRef oDiscoveryData _
)

' instance

Dim oHostedGroupInstance
Set oHostedGroupInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$" _
)

oHostedGroupInstance.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

oHostedGroupInstance.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
hostKey

oHostedGroupInstance.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName

oHostedGroupInstance.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
Trim(oObject.Name)

oHostedGroupInstance.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/EscapedGroupName$", _
g_oClusterUtil.EscapeString(oObject.Name)

'oHostedGroupInstance.AddProperty _
' wrap with $...$ when GroupState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupState", _
' oObject.State

With oHostedGroupInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/AutoFailbackType$", _
autoFailbackType
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/Description$", _
description
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowEnd$", _
failbackWindowEnd
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowStart$", _
failbackWindowStart
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailoverPeriod$", _
failoverPeriod
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailoverThreshold$", _
failoverThreshold
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/PersistentState$", _
persistentState

End With

Call oDiscoveryData.AddInstance(oHostedGroupInstance)

Set DiscoverInstanceForHosted = oHostedGroupInstance

End Function

'==========================================================================
' Discover cluster contains relationship instance
'==========================================================================
Public Sub DiscoverClusterGroupContainsRelationship( _
ByVal hostKey, _
ByVal groupKey, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster group contains hosted groups."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", _
hostKey
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", _
Trim(groupKey)

End With

Dim oHostedInstance
Set oHostedInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$" _
)

With oHostedInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
hostKey
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
groupKey

End With

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Group.Contains.Microsoft.Windows.Cluster.HostedGroup']$" _
)

oRelationshipInstance.Source = oInstance
oRelationshipInstance.Target = oHostedInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)

End Sub

End Class ' WinClusterGroup

'==========================================================================
' Class: WinClusterResource
' Description: holding cluster resource extension and its properties
'==========================================================================
Class WinClusterResource

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal clusterKey, _
ByVal groupKey, _
ByRef oObject, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for Microsoft.Windows.Cluster.Resource."

Dim name
Dim typeName
Dim description
Dim isAlivePollInterval
Dim LooksAlivePollInterval
Dim pendingTimeout
Dim persistentState
Dim restartAction
Dim restartPeriod
Dim restartThreshold
Dim retryPeriodOnFailure
Dim separateMonitor

name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
typeName = g_oClusterUtil.WMIGetProperty ( oObject, "Type", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
isAlivePollInterval = g_oClusterUtil.WMIGetProperty ( oObject, "IsAlivePollInterval", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
looksAlivePollInterval = g_oClusterUtil.WMIGetProperty ( oObject, "LooksAlivePollInterval", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
pendingTimeout = g_oClusterUtil.WMIGetProperty ( oObject, "PendingTimeout", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
persistentState = g_oClusterUtil.WMIGetProperty ( oObject, "PersistentState", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )
restartAction = g_oClusterUtil.WMIGetProperty ( oObject, "RestartAction", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
restartPeriod = g_oClusterUtil.WMIGetProperty ( oObject, "RestartPeriod", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
restartThreshold = g_oClusterUtil.WMIGetProperty ( oObject, "RestartThreshold", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
retryPeriodOnFailure = g_oClusterUtil.WMIGetProperty ( oObject, "RetryPeriodOnFailure", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
separateMonitor = g_oClusterUtil.WMIGetProperty ( oObject, "SeparateMonitor", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']$" _
)

With oInstance

.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
name

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
clusterKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
groupKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceName$", _
Trim(name)

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/EscapedResourceName$", _
g_oClusterUtil.EscapeString(name)

'Dim state
'state = g_oClusterUtil.WMIGetProperty ( oObject, "State", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
'
'.AddProperty _
' wrap with $...$ when ResourceState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceState", _
' state

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceTypeName$", _
typeName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/Description$", _
description
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/IsAlivePollInterval$", _
isAlivePollInterval
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/LooksAlivePollInterval$", _
looksAlivePollInterval
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/PendingTimeout$", _
pendingTimeout
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/PersistentState$", _
persistentState
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartAction$", _
restartAction
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartPeriod$", _
restartPeriod
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartThreshold$", _
restartThreshold
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RetryPeriodOnFailure$", _
retryPeriodOnFailure
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/SeparateMonitor$", _
separateMonitor

End With

Call oDiscoveryData.AddInstance(oInstance)

Set DiscoverInstance = oInstance

End Function

'==========================================================================
' Discover group hostinging resources relationship instance
'==========================================================================
Public Sub DiscoverClusterGroupHostsResourcesRelationship( _
ByVal hostKey, _
ByVal groupKey, _
ByVal resKey, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for group containing resources.."

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$" _
)

With oInstance
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
hostKey
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
groupKey
End With

Dim oClusterResourceInstance
Set oClusterResourceInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']$" _
)

With oClusterResourceInstance


.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
hostKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
groupKey

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceName$", _
resKey

End With

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup.Hosts.Microsoft.Windows.Cluster.Resource']$" _
)

oRelationshipInstance.Source = oInstance
oRelationshipInstance.Target = oClusterResourceInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)

End Sub

End Class ' WinClusterResource

'==========================================================================
' Description: HELPERS
'==========================================================================

Class Error
Public Description
Public Number
Public Source

Sub Class_Initialize()
Number = 0
End Sub

Sub Save
Description = Err.Description
Number = Err.Number
Source = Err.Source
Err.Clear
End Sub

Sub Raise(strDescription)
Err.Raise Number, Source, strDescription &amp; GetErrorString(Number, Description)
End Sub
End Class

'==========================================================================
' Class: ClusterUtil
' Description: Utility methods for clustering
'==========================================================================
Class ClusterUtil

'**********************************************************************
Public Function EscapeString(ByVal sText)
Const METACHARACTERS = """\"
Dim sResult
Dim i
For i = 1 To Len(sText)
Dim sCurrentChar
sCurrentChar = Mid(sText, i, 1)
If InStr(METACHARACTERS, sCurrentChar) &lt;&gt; 0 Then
sResult = sResult &amp; "\"
End If
sResult = sResult &amp; sCurrentChar
Next
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"ESCAPEd string: " &amp; sResult
EscapeString = sResult
End Function

'**********************************************************************
Function WMIExecQuery(ByVal sNamespace, ByVal sQuery)

Dim oWMI, oQuery, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" &amp; sNamespace &amp; "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If

On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
e.Save
On Error Goto 0
If IsEmpty(oQuery) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query '" &amp; sQuery &amp; "' returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oQuery.Count
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query '" &amp; sQuery &amp; "' did not return any valid instances. Please check to see if this is a valid WMI Query.", e
End If

Set WMIExecQuery = oQuery

End Function

'**********************************************************************
Function WMIGetInstances(ByVal sNamespace, ByVal sInstance)

Dim oWMI, oInstance, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" &amp; sNamespace &amp; "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If

On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
e.Save
On Error Goto 0
If IsEmpty(oInstance) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The class name '" &amp; sInstance &amp; "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty

On Error Resume Next
nInstanceCount = oInstance.Count
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The class name '" &amp; sInstance &amp; "' did not return any valid instances. Please check to see if this is a valid WMI class name.", e
End If

Set WMIGetInstances = oInstance

End Function

'**********************************************************************
Function WMIGetInstance(ByVal sNamespace, ByVal sInstancePath)

Dim oWMI, oInstance, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" &amp; sNamespace &amp; "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If

On Error Resume Next
Set oInstance = oWMI.Get(sInstancePath)
e.Save
On Error Goto 0
If IsNull(oInstance) Then
g_oUtil.ThrowScriptError "The class name '" &amp; sInstancePath &amp; "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If

Set WMIGetInstance = oInstance

End Function

'**********************************************************************
Function WMIGetProperty(oWmi, sPropName, nCIMType, ErrAction)
Dim sValue, oWmiProp

If Not IsValidObject(oWmi) Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "Accessing property on invalid WMI object.", Err

If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If

WMIGetProperty = ""
Exit Function
End If

On Error Resume Next
Set oWmiProp = oWmi.Properties_.Item(sPropName)
If Err.Number &lt;&gt; 0 Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" &amp; sPropName &amp; "'.", Err

If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If

End If
On Error Goto 0

If IsValidObject(oWmiProp) Then
sValue = oWmiProp.Value

If IsNull(sValue) Then
'
' If value is null, return blank to avoid any issues
'
WMIGetProperty = ""

Else

Select Case (nCIMType)
Case wbemCimtypeString:
If Not oWmiProp.IsArray Then
WMIGetProperty = CStr(sValue)
Else
WMIGetProperty = Join(sValue, ", ")
End If
Case wbemCimtypeSint16, wbemCimtypeSint32, wbemCimtypeReal32, wbemCimtypeReal64, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
If Not oWmiProp.IsArray Then
WMIGetProperty = Trim(CStr(sValue))
Else
WMIGetProperty = Join(sValue, ", ")
End If
Case wbemCimtypeBoolean:
If sValue = 1 Or UCase(sValue) = "TRUE" Then
WMIGetProperty = "True"
Else
WMIGetProperty = "False"
End If
Case wbemCimtypeDatetime:

Dim sTmpStrDate
'
' First attempt to convert the whole wmi date string
'
sTmpStrDate = Mid(sValue, 5, 2) &amp; "/" &amp; _
Mid(sValue, 7, 2) &amp; "/" &amp; _
Left(sValue, 4) &amp; " " &amp; _
Mid (sValue, 9, 2) &amp; ":" &amp; _
Mid(sValue, 11, 2) &amp; ":" &amp; _
Mid(sValue, 13, 2)
If IsDate(sTmpStrDate) Then
WMIGetProperty = CDate(sTmpStrDate)
Else

'
' Second, attempt just to convert the YYYYMMDD
'
sTmpStrDate = Mid(sValue, 5, 2) &amp; "/" &amp; _
Mid(sValue, 7, 2) &amp; "/" &amp; _
Left(sValue, 4)
If IsDate(sTmpStrDate) Then
WMIGetProperty = CDate(sTmpStrDate)
Else
'
' Nothing works - return passed in string
'
WMIGetProperty = sValue
End If
End If
Case Else:
WMIGetProperty = ""
End Select
End If
Else

If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" &amp; sPropName &amp; "'.", Err

If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If

WMIGetProperty = ""

End If

If (ErrAction And ErrAction_Trace) = ErrAction_Trace Then _
WScript.Echo " + " &amp; sPropName &amp; " :: '" &amp; WMIGetProperty &amp; "'"

End Function

'**********************************************************************
Public Function IsValidObject(ByVal oObject)
IsValidObject = False
If IsObject(oObject) Then
If Not oObject Is Nothing Then
IsValidObject = True
End If
End If
End Function

'==========================================================================
' Discover cluster contains relationship instance
'==========================================================================
Public Sub DiscoverClusterContainsRelationship( _
ByRef oSourceInstance, _
ByRef oTargetInstance, _
ByVal discoveryRelationshipClass, _
ByRef oDiscoveryData _
)

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains objects."

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
discoveryRelationshipClass _
)

oRelationshipInstance.Source = oSourceInstance
oRelationshipInstance.Target = oTargetInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)

End Sub

End Class 'ClusterUtil

'==========================================================================
' Class: Util
' Description: Utility methods for logging
'==========================================================================
Class Util

'**********************************************************************
Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
On Error Resume Next
LogMessage _
DBG_ERROR, _
sMessage &amp; vbCrLf &amp; oErr.Description

oAPI.LogScriptEvent "DiscoverClustering.vbs", 7001, 1, "Discovery script failed. Possible causes include Cluster Service or WMI Service not running. The error was: " &amp; sMessage &amp; " " &amp; oErr.Description
End Function

'**********************************************************************
Public Function ThrowScriptError(Byval sMessage, ByVal oErr)
On Error Resume Next
ThrowScriptErrorNoAbort sMessage, oErr

'switch to incremental discovery and return
'empty snapshot, preventing the script failure
'from triggering an alert
ThrowEmptyDiscoveryData(false)

Quit
End Function

Public Function Quit
LogMessage _
DBG_ERROR, _
"Terminated on error!"

Wscript.Quit -1
End Function

' Used to say to LogMessage when/how to print the message.
Public DBG_NONE
Public DBG_ERROR
Public DBG_WARNING
Public DBG_TRACE

'Internal Debug Level
Private m_nDebugLevel

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
' Initialize Debug level constants
DBG_TRACE = 1
DBG_WARNING = 2
DBG_ERROR = 3
DBG_NONE = 4

'by default only errors are logged
m_nDebugLevel = DBG_ERROR

End Sub

'======================================================================
' Method: GetCurrentLevel
' Description: retrieve current logging level.
' Parameters:
'======================================================================
Public Function GetCurrentLevel()
GetCurrentLevel = m_nDebugLevel
End Function

'======================================================================
' Method: SetDebugLevel
' Description: To change the debugging output level of information
' generated by this utility.
' Parameters:
' nLevel - DBG_NONE, DBG_TRACE, DBG_WARNING or DBG_ERROR
'======================================================================
Public Sub SetDebugLevel(ByVal nLevel)
m_nDebugLevel = nLevel
End Sub

'======================================================================
' Method: LogMessage
' Description: Log a debug message to ScriptContext
' Parameters:
' nLevel - Debug level for the message that
' we're logging.
' strMessage - The message to write to the trace.
'======================================================================
Public Sub LogMessage( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel &gt;= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo "[Error]: " &amp; strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo "[Warning]: " &amp; strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo "[Trace]: " &amp; strMessage
End If
End If
End Sub
Public Sub LogMessageNewLine( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel &gt;= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo vbCrLf &amp; "[Error]: " &amp; strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo vbCrLf &amp; "[Warning]: " &amp; strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo vbCrLf &amp; "[Trace]: " &amp; strMessage
End If
End If
End Sub

End Class ' Util</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="Script"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>