Cluster Discovery Script (with resource filter)

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

Discovery script module for Windows Server Cluster.

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.Cluster.CommandExecuterProbeDiscoveryBase Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
DiscoverUnusedNetworksbool$Config/DiscoverUnusedNetworks$Discover Unused Networks
AppendClusterNameToResourceGroupNamebool$Config/AppendClusterNameToResourceGroupName$Append Cluster Name To Resource Group Name
DiscoverCSVResourcesbool$Config/DiscoverCSVResources$Discover Cluster Shared Volume Resources
DiscoverNonCSVResourcesbool$Config/DiscoverNonCSVResources$Discover Cluster Resources
ResourceGroupDiscoveryLimitint$Config/ResourceGroupDiscoveryLimit$Resource Group Discovery Limit
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds
ResourceGroupTypeFilterstring$Config/ResourceGroupTypeFilter$Resource Group Type Filter

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"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="OSVersion" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="ComputerName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="NetBiosName" 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="Microsoft.Windows.Cluster.CommandExecuterProbeDiscoveryBase">
<ApplicationName>%SystemRoot%\system32\cmd.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>/c $file/Main.cmd$</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Main.cmd</Name>
<Contents><Script>

@echo off

set psscript=DiscoverClustering.ps1
set vbscript=DiscoverClustering.vbs
set cscript=%windir%\system32\cscript.exe
set ps=%windir%\system32\WindowsPowerShell\v1.0\powershell.exe
set params=

if Exist "%cscript%" goto vb
if Exist "%ps%" goto pshell
goto end
:vb
if not exist "%~dp0%vbscript%" goto end

if exist "%~dp0vbparams.txt" (
set /p params=&lt;"%~dp0vbparams.txt"
)

"%cscript%" /nologo "%~dp0%vbscript%" %params%
goto end
:pshell
if not exist "%~dp0%psscript%" goto end

if exist "%~dp0psparams.txt" (
set /p params=&lt;"%~dp0psparams.txt"
)
"%ps%" -nologo -EP bypass -command "&amp; '%~dp0%psscript%'" %params%
goto end

:end
If %ERRORLEVEL% NEQ 0 (
exit %ERRORLEVEL%
)



</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>DiscoverClustering.ps1</Name>
<Contents><Script>param(
$SourceId
,$ManagedEntityId
,$HealthServiceName
,$NetBiosName
,$discoverUnusedNetworks
,$networkContainsInterfaceGuid
,$networkInterfaceTypeGuid
,$networkInterfacePropClusterNameGuid
,$networkInterfacePropNameGuid
,$discoverCSVResources
,$discoverNonCSVResources
,$ResourceGroupDiscoveryLimit
,$appendClusterNameToResourceGroup
,$strNetworkInterfacePropClusterAdapterID
,$strResourceGroupTypeFilter
,$OsVersion
)


#=================================
#Global Variables
##################################
$oAPI = $null
#====================================
# Log Constants
#=====================================
$DBG_NONE = 0
$DBG_ERROR = 1
$DBG_WARNING = 2
$DBG_TRACE = 4
$EventId = 7002
$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2
$ObjectNameStringMaxSize = 4000
#=====================================
# String Constants
#=====================================
$ScriptName = "DiscoverClustering.ps1"
$DefaultClusterGroupTypes = ""

$StartParametersMsg = @"

Windows Cluster Discovery
SourceId: {0} ManagedEntityId : {1} HealthServiceName : {2} NetBiosName : {3} discoverUnusedNetworks : {4}
networkContainsInterfaceGuid : {5} networkInterfaceTypeGuid : {6} networkInterfacePropClusterNameGuid : {7}
networkInterfacePropNameGuid : {8} discoverCSVResources : {9} discoverNonCSVResources : {10}
ResourceGroupDiscoveryLimit : {11} appendClusterNameToResourceGroup : {12}
strNetworkInterfacePropClusterAdapterID : {13} strResourceGroupTypeFilter : {14} OsVersion : {15}
"@
$StartDiscoveryMsg = "Started cluster dicovery at machine local time:"
$FinishDiscoveryMsg = "Finished cluster dicovery at machine local time: "
$CreateDiscoveryDataErrorMsg = "Failed to get Discovery Data Object. MOM v3 must be installed to execute this script."
$InitApiErrorMsg = "Failed to get Discovery API. MOM v3 must be installed to execute this script. Error:{0}"
$InitScomSerApiErrorMsg = "Failed to Initialize SCOM Discovery Serialization API. MOM v3 must be installed to execute this script."
$StartNetworkRelDiscoveryMessage = "Creating DiscoveryData packet for cluster contains network."
$StartNetworkIfRelDiscoveryMessage = "Creating DiscoveryData packet for cluster network contains network interfaces."
$StartNodeDiscoveryMessage = "Creating DiscoveryData packet for Microsoft.Windows.Cluster.Node on cluster [{0}]"
$StartNodeHostingDiscoveryMessage = "Creating DiscoveryData packet for node hosting roles."
$StartNodeContainsDiscRelMessage = "Creating DiscoveryData packet for cluster contains nodes."
$StartWinClusterInstDiscoveryMsg = "Creating DiscoveryData packet for [{0}]."
$StartWinClusterDiscoveryMsg = "Creating DiscoveryData packet for Windows Cluster [{0}]."

$ErrorStartParametersMsg = "Minimal list of parameters is empty. Exiting discovery. SourceId: {0} ManagedEntityId : {1} HealthServiceName : {2} NetBiosName : {3} "
$ErrorNodeDiscoveryMessage = "DiscoveryData packet for Microsoft.Windows.Cluster.Node on cluster [{0}]. Cannot create {1}."
$ErrorAddNodeDiscoveryMessage = "DiscoveryData packet for Microsoft.Windows.Cluster.Node on cluster [{0}]. Cannot add instance of {1}."
$ErrorNodeMessage = "Microsoft.Windows.Cluster.Node discovery instance"
$ErrorNodeHostingDiscoveryMessage = "DiscoveryData packet for node hosting roles. Cannot create {0}."
$ErrorNodeHostingRelDisMessage = "DiscoveryData packet for node hosting roles. Cannot create RelationShip Instance of {0}."
$ErrorAddNodeHostingDiscMessage = "DiscoveryData packet for node hosting roles. Cannot add RelationShip. Error: {0}."
$ErrorNetworkRelDiscMessage = "Creating DiscoveryData packet for cluster contains network. Cannot create Instance of {0}."
$ErrorNetIfRelDiscoveryMessage = "Creating DiscoveryData packet for cluster network contains network interfaces. Cannot create Instance Of {0}."
$ErrorNetIfRelDisMessage = "Creating DiscoveryData packet for cluster network contains network interfaces. Cannot create RelationShip Instance of {0}."
$ErrorAddNetIfRelDiscMessage = "Creating DiscoveryData packet for cluster network contains network interfaces. Cannot add RelationShip. Error: {0}."
$ErrorWinClusterInstDiscoveryMsg = "Creating DiscoveryData packet for [{0}]. Cannot create new Instance. Error:{1}"
$ErrorNodeContainDiscRelsMsg = "Creating DiscoveryData packet for cluster contains nodes. Cannot create new Instance. Error:{0}"
$ErrorNodeAddContainDiscRelMsg = "Creating DiscoveryData packet for cluster contains nodes. Cannot add new relationship. Error:{0}"
$ErrorWinClusterDiscoveryMsg = "Creating DiscoveryData packet for Windows Cluster [{0}]. Cannot create new Instance. Error:{1}"
$ErrorSaveClusterDiscoveryMsg = "Creating DiscoveryData packet for Windows Cluster [{0}]. Cannot save Instance. Error:{1}"
$ErrorAddClusterDiscoveryMsg = "Creating DiscoveryData packet for Windows Cluster [{0}]. Cannot Add Instance to discovery. Error:{1}"
$ErrorClNetworkDiscMessage = "Discovery cluster networks. Cannot add cluster networks for cluster {0}. Error: {1}"
$ErrorClNodesDiscMessage = "Discovery cluster nodes. Cannot add cluster nodes for cluster {0}. Error: {1}"
$ErrorGrpsNodesDiscMessage = "Discovery cluster groups. Cannot add cluster groups for cluster {0}. Error: {1}"
$ClusterGroupGetErrorMessage = "Cannot get Cluster Groups on cluster [{0}]. Please check to see if this is a valid WMI Query."
$ClusterGroupGetActiveNodeErrorMessage = "The Query for active node returned an invalid result set on cluster [{0}]. Please check to see if this is a valid WMI Query."
$ErrorClusterGroupResourceLimit = "{0} hosts more than {1} resource groups which exceeds the configured threshold of {2} ."

Function LogMessage($nLevel, $strMessage,$LogId = $EventId)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function

if($nLevel -eq $DBG_ERROR)
{
Write-Host "[Error]: " $strMessage;
}elseif ($nLevel -eq $DBG_WARNING)
{
Write-Host "[Warning]: " $strMessage;
} elseif ($nLevel -eq $DBG_TRACE)
{
Write-Host "[Trace]: " $strMessage;
}
else
{
Write-Host $strMessage
}
$Error.Clear()

if ($nLevel -ne $DBG_WARNING -or $nLevel -ne $DBG_ERROR)
{
return
}

if ($null -eq $oAPI)
{
$oAPI = New-Object -ComObject "MOM.ScriptAPI"
if ($null -eq $oAPI)
{
return $null
}
}

if ($null -eq $LogId)
{
$LogId = 7002
}

$oAPI.LogScriptEvent($ScriptName,$LogId,$nLevel,$Message)
}

Function Init-ScomHelper
{
$DiscHelper = @'
namespace SCOM.Helper
{
using System;
using System.Runtime.InteropServices;
public class ConvertData
{

public static string GetDataItemFromOutput(
Object oData)
{
NativeMethods.ISerialize discoverySerializer = null;
discoverySerializer = oData as NativeMethods.ISerialize;
string xmlString = null;
if (null != discoverySerializer)
{
int hr = discoverySerializer.SaveToString(out xmlString);
Marshal.ThrowExceptionForHR(hr);
}

return xmlString;
}

public static class NativeMethods
{
[Guid("A4E79E8A-9494-47A4-A280-8C7D35C88A2F"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISerialize
{
int SaveToString([MarshalAs(UnmanagedType.BStr)] out string output);
int LoadFromString([MarshalAs(UnmanagedType.BStr)] string input);
}
}
}
}

'@

$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
Add-Type $DiscHelper

$result = 0 -eq $Error.Count

return $result
}
########################################################
##Wmi-Helpers
########################################################
Function Check-CimType($Object)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$result = $false

if ($null -eq $Object)
{
return $null
}

$type = $Object.GetType()
if ($null -eq $type)
{
return $null
}

$TypeName = $type.FullName

if ([string]::IsNullOrEmpty($TypeName))
{
return $null
}

$result = "Microsoft.Management.Infrastructure.CimInstance" -eq $TypeName

if ($false -eq $result -and "System.Management.ManagementObject" -ne $TypeName )
{

$result = $null
}

return $result
}

Function CheckCimModule()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$cim = Get-Module -Name CimCmdlets

########Check for powershell 1.0
if ($error.Count -ne 0)
{
if ($null -eq $error[0].Exception)
{
return $retval
}

$type = $error[0].Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
return $retval
}

$error.Clear()
}

if ($null -eq $cim)
{
Import-Module CimCmdLets
if ($error.Count -eq 0)
{
$retval = $true
}

$error.Clear()
}
else
{
$retval = $true
}

return $retval
}

function CheckCmdLets()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$objSWbemObjectSet =$null

if (CheckCimModule)
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$objSWbemObjectSet = Get-CimInstance -CimSession $cimsession -Class Win32_OperatingSystem
}
catch
{
$objSWbemObjectSet = Get-WMIObject -Class Win32_OperatingSystem
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -eq 0)
{
$retval = $true
}
}

$error.Clear()
return $retval;
}


Function Get-WmiErrorCode($Exception)
{
$result = -1
if ($null -eq $Exception)
{
return 0
}

$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$type = $Exception.GetType()
if ($error.Count -ne 0)
{
$error.Clear()
return $result
}

if ("Microsoft.Management.Infrastructure.CimException" -eq $type.FullName)
{
$result = $Exception.ErrorData.Error_code
}
elseif($type -eq [System.Management.ManagementException] )
{
$result = $Exception.ErrorCode.value__
}
elseif($type -eq [System.Management.Automation.RuntimeException])
{
$result = $Exception.HResult
if ($null -eq $result)
{
$result = 0
}
}

return $result

}

Function Check-WmiExceptions($Exception)
{
$result = $false
if ($null -eq $Exception)
{
return $result
}

$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$type = $Exception.GetType()
if ($error.Count -ne 0)
{
$error.Clear()
return $result
}

if ("Microsoft.Management.Infrastructure.CimException" -eq $type.FullName)
{
$result = Check-CimException -Exception $Exception
}
elseif($type -eq [System.Management.ManagementException] )
{
$result = Check-WmiException -Exception $Exception
}

return $result
}

Function Check-WmiException ([System.Management.ManagementException] $Exception)
{
$WMI_ERROR_INVALIDCLASS = -2147217392
$WMI_ERROR_INVALIDNAMESPACE = -2147217394
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$bresult = $false
$ErrorCode = $Exception.ErrorCode.value__

if ($WMI_ERROR_INVALIDCLASS -eq $ErrorCode -or $WMI_ERROR_INVALIDNAMESPACE -eq $ErrorCode)
{
$bresult = $true
}

return $bresult

}

Function Check-CimException ( $Exception)
{
$CIM_ERROR_INVALIDCLASS = 2147749902
$CIM_ERROR_INVALIDNAMESPACE = 2147749904
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$bresult = $false
#Invalid ClassName or NameSpace
$ErrorCode = $Exception.ErrorData.Error_code
if ($CIM_ERROR_INVALIDCLASS -eq $ErrorCode -or $CIM_ERROR_INVALIDNAMESPACE -eq $ErrorCode)
{
$bresult = $true
}

return $bresult

}

Function WMIGetAssociatorInstanceNoAbort
{
param (
[string]$ComputerName,
[string]$sNamespace,
[string]$sAssociatorName,
[string]$sWmiAssociatorName,
$oWmiInstance,
[bool] $useCim
)

$ErrorActionPreference = 'SilentlyContinue'
if ([string]::IsNullOrEmpty($ComputerName))
{
$ComputerName = "."
}

$KerberosErrorCode = 2147943712
$ConnectionErrorCode = 2147942453

$Error.Clear()

if ($true -eq $useCim)
{
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
$oInstance = Get-CimAssociatedInstance -CimSession $cimsession -InputObject $oWmiInstance -Association $sAssociatorName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorData.Error_code
If ($KerberosErrorCode -eq $ErrorCode -or $ConnectionErrorCode -eq $ErrorCode)
{
$error.Clear()

try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimAssociatedInstance -CimSession $cimsession -InputObject $oWmiInstance -Association $sAssociatorName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
}
}
else
{

if($false -eq [string]::IsNullOrEmpty($oWmiInstance))
{
$ErrorActionPreference = 'SilentlyContinue'
$oInstance = $oWmiInstance.GetRelated($sWmiAssociatorName)
}
else
{
$oInstance = $null
}
}

return $oInstance
}

Function WMIGetInstanceNoAbort
{
param (
[string]$ComputerName,
[string]$sNamespace,
[string]$sClassName,
[string]$sFilter,
[bool] $useCim
)

$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$KerberosErrorCode = 2147943712
$ConnectionErrorCode = 2147942453
$WmiConnectErrorCode = -2147023174

if ([string]::IsNullOrEmpty($ComputerName))
{
$ComputerName = "."
}

if ([string]::IsNullOrEmpty($sNamespace))
{
$sNamespace = "root\cimv2"
}

if ($true -eq $useCim)
{
$oInstance = $null
if ([string]::IsNullOrEmpty($sFilter))
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -ComputerName $ComputerName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorData.Error_code
If ($KerberosErrorCode -eq $ErrorCode -or $ConnectionErrorCode -eq $ErrorCode)
{
$error.Clear()
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
}
}
else
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -ComputerName $ComputerName -Filter $sFilter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorData.Error_code
If ($KerberosErrorCode -eq $ErrorCode -or $ConnectionErrorCode -eq $ErrorCode)
{
$error.Clear()
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
}

}
}
else
{
$oInstance = $null
if ([string]::IsNullOrEmpty($sFilter))
{
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -ComputerName $ComputerName
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorCode
If ($WmiConnectErrorCode -eq $ErrorCode)
{
$error.Clear()
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace
}
}
}
else
{
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -Filter $sFilter -ComputerName $ComputerName
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorCode
If ($WmiConnectErrorCode -eq $ErrorCode)
{
$error.Clear()
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -Filter $sFilter
}
}

}
}

return $oInstance
}

Function Get-CimInstanceKeyValue( [ciminstance] $InputObject)
{
$ErrorActionPreference = "SilentlyContinue"

$KeyValuePair = @()
If ($null -eq $InputObject)
{
return $KeyValuePair
}

$keyMask = [Microsoft.Management.Infrastructure.CimFlags]::Key

foreach($Property in $InputObject.CimInstanceProperties)
{
if(0 -ne( $Property.Flags -band $keyMask) )
{
$Value = Get-CimPropertyValue -Property $Property
if ($null -ne $Value)
{
$KeyName = "{0}={1}" -f $Property.Name, $Value
$KeyValuePair += $KeyName
}

}
}

return $KeyValuePair
}

Function Get-CimPropertyValue([Microsoft.Management.Infrastructure.CimProperty]$Property)
{
$Pt = $Property.CimType
if ( $Property.CimType -eq [Microsoft.Management.Infrastructure.CimType]::String )
{
$Value = '"{0}"' -f (($Property.Value -replace "`"", "\`"") -replace "\\","\\")
}
elseif ([Microsoft.Management.Infrastructure.CimType]::Boolean -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::UInt8 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::UInt16 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::UInt32 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::UInt64 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::SInt8 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::SInt16 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::SInt32 -eq $Property.CimType -or [Microsoft.Management.Infrastructure.CimType]::SInt64 -eq $Property.CimType)
{
$Value = $Property.Value
}
elseif([Microsoft.Management.Infrastructure.CimType]::DateTime -eq $Property.CimType )
{
$Value = '"{0}"' -f [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($Property.Value)
}
else
{
$Value = '"{0}"' -f (($Property.Value -replace "`"", "\`"") -replace "\\","\\")

}

return $Value
}

Function Get-CimFromInstance ( $InputObject)
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()

$Keys = Get-CimInstanceKeyValue -InputObject $InputObject
$Filter = $null
$oInstance = $null
if (0 -ne $Keys.Count)
{
$Filter = [string]::Join(" and ",$Keys)
}

if (0 -ne $error.Count)
{
return $oInstance
}


$ClassName = $InputObject.CimClass.CimSystemProperties.ClassName
$NameSpace = $InputObject.CimClass.CimSystemProperties.Namespace
$ComputerName = $InputObject.CimClass.CimSystemProperties.ServerName
if ([string]::IsNullOrEmpty($ClassName) -or [string]::IsNullOrEmpty($NameSpace) -or [string]::IsNullOrEmpty($ComputerName) )
{
return $oInstance
}

Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $NameSpace -ClassName $ClassName -Filter $Filter
}
catch
{
$oInstance = Get-WMIObject -Namespace $NameSpace -ClassName $ClassName -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

return $oInstance
}

Function Get-WmiInstanceFromPath([string]$computerName, [string]$Namespace,[string]$InstancePath)
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()
$WmiPath = "\\$computerName\$Namespace" + ":" + $InstancePath
$oInstance = $null
$oInstance = [wmi]$WmiPath

return $oInstance
}

Function WMIGetInstance([string]$computerName, [string]$sNamespace,$sInstancePath)
{

$oInstance =$null
if ([string]::IsNullOrEmpty($sInstancePath))
{
return $oInstance
}

if("Microsoft.Management.Infrastructure.CimInstance" -eq $sInstancePath.GetType().FullName)
{
$oInstance = Get-CimFromInstance -InputObject $sInstancePath
}
elseif([string] -eq $sInstancePath.GetType())
{
$oInstance = Get-WmiInstanceFromPath -computerName $computerName -Namespace $sNamespace -InstancePath $sInstancePath
}

return $oInstance
}

Function Load-CimModules
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()

}
}




##########################################################################
#Windows Cluster Helpers
##########################################################################
Function Get-WinClusters([string]$computerName,[bool]$UseCim)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$oClusters = $null
$NameSpace = "root\mscluster"
$ClassName = "MSCluster_Cluster"

$oClusters = WMIGetInstanceNoAbort -ComputerName $computerName -sNamespace $NameSpace -sClassName $ClassName -sFilter $null -useCim $UseCim
return $oClusters
}

Function Get-ClusterObjects($oCluster,[string]$ComputerName,[string]$AssociatorName,[string]$WmiClassName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$Objects = $null
$Namespace = "root\mscluster"

$useCim = Check-CimType -Object $oCluster
if ($null -ne $useCim)
{
$Objects = WMIGetAssociatorInstanceNoAbort -ComputerName $ComputerName -sNamespace $Namespace -sAssociatorName $AssociatorName -sWmiAssociatorName $WmiClassName -oWmiInstance $oCluster -useCim $useCim
}

return $Objects
}

Function Get-ClusterNodes($oCluster,[string]$ComputerName,[string]$NodeNameFilter)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_Node"
$AssocName = "MSCluster_ClusterToNode"
$NameProperty = "Name"

$oNodes = Get-ClusterObjects -oCluster $oCluster -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

if ($null -ne $oNodes -and $false -eq [string]::IsNullOrEmpty($NodeNameFilter))
{
$oNodes = $oNodes | Where-Object {$_.Name -eq $NodeNameFilter}

if ($oNodes.Count -gt 1)
{
$oNodes = $oNodes[0]
}
}

return $oNodes
}

Function Get-ClusterNetworks($oCluster,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_Network"
$AssocName = "MSCluster_ClusterToNetwork"

$oNetworks = Get-ClusterObjects -oCluster $oCluster -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

return $oNetworks
}

Function Get-ClusterNetworkInterfaceFromNet($oNet,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_NetworkInterface"
$AssocName = "MSCluster_NetworkToNetworkInterface"

$oNics = Get-ClusterObjects -oCluster $oNet -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

return $oNics
}
Function Get-ClusterGroups($oCluster,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_ResourceGroup"
$AssocName = "MSCluster_ClusterToResourceGroup"

$oGroups = Get-ClusterObjects -oCluster $oCluster -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

return $oGroups
}

Function Get-ClusterNetInterfaces($oNetwork,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_NetworkInterface"
$AssocName = "MSCluster_NetworkToNetworkInterface"

$oNics = Get-ClusterObjects -oCluster $oNetwork -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

return $oNics
}

Function Get-ClusterResourceInGroup($oGroup,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_Resource"
$AssocName = "MSCluster_ResourceGroupToResource"

$oResources = Get-ClusterObjects -oCluster $oGroup -ComputerName $ComputerName -AssociatorName $AssocName -WmiClassName $ClassName

return $oResources
}

Function Get-CsvResourcesInGroup($oGroup,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClassName = "MSCluster_Resource"
$Filter = "IsClusterSharedVolume = true"
$Namespace = "root\mscluster"
$oResources = $null

$WMI_INVALID_QUERY = -2147217385
$CIM_INVALID_QUERY = 2147749911

$useCim = Check-CimType -Object $oGroup
if ($null -ne $useCim)
{
$oResources = WMIGetInstanceNoAbort -ComputerName $ComputerName -sNamespace $Namespace -sClassName $ClassName -sFilter $Filter -useCim $useCim
if (0 -ne $error.Count)
{
$errorCodeWmi = $error[0].Exception.ErrorCode.value__
$errorCodeCim = $error[0].Exception.ErrorData.Error_code
if($WMI_INVALID_QUERY -eq $errorCodeWmi -or $CIM_INVALID_QUERY -eq $errorCodeCim)
{
$oResources =$null
$error.Clear()
$oResources =$null
}
}
}

return $oResources
}

Function Get-ResourceGroupType($oGroup)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$CimErrorMethodNotFound = 2147744890
$GroupType = $null
if ($null -eq $oGroup)
{
return $GroupType
}

$GroupType = $oGroup.GroupType

if ($null -eq $GroupType)
{
$useCim = Check-CimType -Object $oGroup
if ($null -ne $useCim)
{
if ($true -eq $useCim)
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$GroupType = ($oGroup | Invoke-CimMethod -CimSession $cimsession -MethodName "GetGroupType").ReturnValue
}
catch
{
$GroupType = ($oGroup | Invoke-WmiMethod -Name "GetGroupType").ReturnValue
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if (0 -ne $error.Count)
{
$Exception = $error[0].Exception
$ErrorCode = Get-WmiErrorCode -Exception $Exception
If ($CimErrorMethodNotFound -eq $ErrorCode -or -1 -eq $ErrorCode -or 0 -eq $ErrorCode)
{
$GroupType = $null
$error.Clear()
}


}

}
else
{
if ($null -ne $Group.GetGroupType)
{
if ([System.Management.Automation.PSMethod] -eq $Group.GetGroupType.GetType())
{
$GroupType = $Group.GetGroupType().ReturnValue
if (0 -ne $error.Count)
{
$GroupType = $null
$error.Clear()
}

}

}
}


}

}

return $GroupType
}

Function Get-GroupsToActiveNode($oCluster,[string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$Objects = $null
$NameSpace = "root\mscluster"
$ClassName = "MSCluster_NodeToActiveGroup"
$GroupsToNodeObjects = @{}

$useCim = Check-CimType -Object $oCluster
$error.Clear()
if ($null -ne $useCim)
{
$Objects = WMIGetInstanceNoAbort -ComputerName $ComputerName -sNamespace $NameSpace -sClassName $ClassName -sFilter $null -useCim $useCim
}
else
{
return $GroupsToNodeObjects
}

if (0 -ne $error.Count)
{
return $GroupsToNodeObjects
}

foreach($Object in $Objects)
{
$oGroup = $Object.PartComponent
$oNode = $Object.GroupComponent
if (0 -ne $error.Count -or $null -eq $oGroup -or $null -eq $oNode)
{
$GroupsToNodeObjects = @{}
return $GroupsToNodeObjects
}

if ($false -eq $useCim)
{
$Group = $null
$Node = $null
$Group = WMIGetInstance -computerName $ComputerName -sNamespace $NameSpace -sInstancePath $oGroup
$Node = WMIGetInstance -computerName $ComputerName -sNamespace $NameSpace -sInstancePath $oNode
if (0 -ne $error.Count -or $null -eq $Group -or $null -eq $Node)
{
$GroupsToNodeObjects = @{}
return $GroupsToNodeObjects
}

$oGroup = $Group
$oNode = $Node
}

$GroupName = $oGroup.Name
$NodeName = $oNode.Name
if ($true -eq [string]::IsNullOrEmpty($GroupName) -or $true -eq [string]::IsNullOrEmpty($NodeName) -or 0 -ne $error.Count)
{
$GroupsToNodeObjects = @{}
return $GroupsToNodeObjects
}

$GroupsToNodeObjects[$GroupName] = $NodeName


}

return $GroupsToNodeObjects
}





Function Get-NetAdapterByWmi([string]$ComputerName,[string]$NetId,$oObject,[bool]$discoverUnusedNetworks,[bool]$useCim)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$Objects = $null
$Namespace = "root\cimv2"
$ClassName = "Win32_NetworkAdapter"
$Filter = $null

if (-Not [string]::IsNullOrEmpty($NetId))
{
$Filter = "NetConnectionID = ""$NetId"""
}

if ($false -eq $discoverUnusedNetworks)
{
$Filter = $Filter + " and NetConnectionStatus != 0"
}

if ($null -ne $useCim)
{
$Objects = WMIGetInstanceNoAbort -ComputerName $ComputerName -sNamespace $Namespace -sClassName $ClassName -sFilter $Filter -useCim $useCim
}

return $Objects
}

Function Check-NicWmi([string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$ClassName = "Win32_NetworkAdapter"
$ClassNotFoundError = 2147749890
$NameSpace = "root\cimv2"

$result = 1
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$NetClass = Get-CimClass -CimSession $cimsession -ClassName $ClassName -Namespace $NameSpace
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if (0 -ne $error.Count )
{
$erCode = $error[0].Exception.ErrorData.error_Code

if ($null -eq $erCode -or $ClassNotFoundError -ne $erCode)
{
$result = 2
}
else
{
$result = 0
}
}

$error.Clear()
return $result
}

Function Get-NicFromWmi([string]$ComputerName,[string]$NetId,$oObject,[bool]$discoverUnusedNetworks)
{
$useCim = Check-CimType -Object $oObject
$Nics = $null


if ($true -eq $useCim)
{
$CheckWmi = Check-NicWmi -ComputerName $ComputerName
if (1 -ne $CheckWmi)
{
return 1
}

}

$Nics = Get-NetAdapterByWmi -ComputerName $ComputerName -NetId $NetId -oObject $oObject -discoverUnusedNetworks $discoverUnusedNetworks -useCim $false

return $Nics

}

Function Get-NicFromPs([string]$NetId,[bool]$discoverUnusedNetworks)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = Load-Module -ModuleName "NetAdapter"

if ($false -eq $result)
{
return $null
}

$Nics = Get-NetAdapter -Name $NetId
if ($false -eq $discoverUnusedNetworks)
{
$Nics = $Nics | where {$_.Status -ne "Disconnected"}
}

return $Nics
}

Function Get-NicData([string]$ComputerName,[string]$NetId,$oObject,[bool]$discoverUnusedNetworks)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$NicData = @{}
$Nics = Get-NicFromWmi -ComputerName $ComputerName -NetId $NetId -oObject $oObject -discoverUnusedNetworks $discoverUnusedNetworks
if(1 -eq $Nics -or ($null -eq $Nics -and 0 -ne $error.Count ))
{
$Nics = Get-NicFromPs -NetId $NetId -discoverUnusedNetworks $discoverUnusedNetworks
$NicData = Get-NicDataFromPsCollection -Nics $Nics
}
else
{
$NicData = Get-NicDataFromWmiCollection -Nics $Nics
}

return $NicData
}

Function Get-NicDataFromWmiCollection($Nics)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$NicData = @{}

if($Nics -eq $null)
{
return $NicData
}

if ($Nics.Count -gt 1)
{
$Nics= $Nics[0]
}

$macAddress = $Nics.MACAddress
if (-Not [string]::IsNullOrEmpty($macAddress))
{
$macAddress = $macAddress.Replace(":", "-")
}

$NicData["deviceID"] = $Nics.DeviceID
$NicData["adapterType"] = $Nics.AdapterType
$NicData["index"] = $Nics.Index
$NicData["manufacturer"] = $Nics.Manufacturer
$NicData["macAddress"] = $macAddress
$NicData["serviceName"] = $Nics.ServiceName

return $NicData
}

Function Get-NicDataFromPsCollection($Nics)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$NicData = @{}

if($Nics -eq $null)
{
return $NicData
}

if ($Nics.Count -gt 1)
{
$Nics= $Nics[0]
}

$serviceName = Get-ServiceName -DriverName $Nics.DriverName
$adapterType = Get-NicAdapterType -MediaType $Nics.NdisMedium
$NicData["deviceID"] = $Nics.DeviceID
$NicData["adapterType"] = $adapterType
$NicData["index"] = $Nics.InterfaceIndex
$NicData["manufacturer"] = $Nics.DriverProvider
$NicData["macAddress"] = $Nics.MACAddress
$NicData["serviceName"] = $serviceName

return $NicData
}

Function Get-NicServiceName($DriverName)
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()

$DriverNameProperty = Get-ServiceNameHelper -DriverName $DriverName
if ($error.Count -ne 0)
{
$DriverNameProperty = [string]::Empty
}

$error.Clear()
return $DriverNameProperty

}

Function Get-NicAdapterType($MediaType)
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()
$result = "Unknown"

if([string]::IsNullOrEmpty($MediaType) )
{
return $result
}

$NdisMediaType = Convert-ToUint32 -Value $MediaType

$AdapterTypes = @{
[uint32]0 = "Ethernet 802.3";[uint32]1 = "Ethernet 802.5";[uint32]2 = "FDDI";[uint32]3 = "WAN";[uint32]4 = "LocalTalk";[uint32]5 = "DIX";[uint32]6 = "Raw Arcnet";
[uint32]7 = "Ethernet 878.2";[uint32]8 = "ATM";[uint32]9 = "Wireless WAN";[uint32]10 = "IRDA";[uint32]11 = "BPC";[uint32]12 = "Connection Oriented WAN";[uint32]13 = "IP 1394";
[uint32]14 = "IB";[uint32]15 = "Tunnel";[uint32]16 = "Native 802.11";[uint32]17 = "Loopback";[uint32]18 = "WiMAX";[uint32]19 = "IP"
}

$result = $AdapterTypes[$NdisMediaType]
if ($null -eq $result)
{
$result = "Unknown"
}

return $result
}

Function Get-ServiceNameHelper([string]$DriverName)
{
$ErrorActionPreference = "SilentlyContinue"

if ([string]::IsNullOrEmpty($DriverName))
{
return [string]::Empty
}

$PathIndex = $DriverName.LastIndexOf("\")

if ($PathIndex -eq ($DriverName.Length - 1))
{
return [string]::Empty
}

$DriverNamePostfix = $DriverName.Substring($PathIndex + 1)
$PathIndex = $DriverNamePostfix.IndexOf(".")

$ServiceName = $DriverNamePostfix
if (-1 -ne $PathIndex )
{
$ServiceName = $DriverNamePostfix.Substring(0,$PathIndex)
}

return $ServiceName

}
Function Load-CimModules
{
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()
}
}


Function Get-StringProperty([string]$Property,[int]$MaxSize = 256,[bool]$Trim=$false)
{
if ([string]::IsNullOrEmpty($Property))
{
return [string]::Empty
}


if($true -eq $Trim)
{
$sProperty = $Property.Trim()
}
else
{
$sProperty = $Property
}

if ($sProperty.Length -gt $MaxSize)
{
$sProperty = $Property.Substring(0,$MaxSize)
}

return $sProperty
}

Function Convert-ToBoolean([string] $sBool)
{
[bool] $result = $false
[bool] $iresult = $false

if ($false -eq [string]::IsNullOrEmpty($sBool) )
{
$result = $sBool.Equals("true",[System.StringComparison]::InvariantCultureIgnoreCase)
$iresult = $sBool.Equals("1",[System.StringComparison]::InvariantCultureIgnoreCase)
$result = $result -or $iresult
}

return $result
}

Function Convert-ToUint32($Value)
{
$ErrorActionPreference = "SilentlyContinue"

$result = [uint32]0

if ([string]::IsNullOrEmpty($value))
{
return $result
}

$result = [uint32]::MaxValue
$type = $Value.GetType()
$error.Clear()

$result = [uint32]$Value
if (0 -eq $error.Count)
{
return $result
}
else
{
$error.Clear()
$Value = [int32]$Value
if (0 -ne $error.Count)
{
$error.Clear()
return $result
}
else
{
if ($Value -lt 0)
{
$result = ([uint32]::MaxValue + $a) + 1
}
else
{
$result = [uint32]$Value
}

}
}

return $result
}

Function Convert-IntToString($Value,[string]$DefaultValue,[bool]$Hex=$false)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = [string]::Empty
if ($false -eq [string]::IsNullOrEmpty($DefaultValue))
{
$result = $DefaultValue
}

$iValue = [int]$Value
if (0 -eq $error.Count)
{
if ($true -eq $Hex)
{
$subresult = ("{0:x}" -f $iValue).ToUpper()
}
else
{
$subresult = "{0}" -f $iValue
}

if (0 -eq $error.Count)
{
$result = $subresult
}
else
{
$error.Clear()
}

}


return $result

}

Function Load-Module ([string] $ModuleName)
{


$ErrorActionPreference="SilentlyContinue"
$error.Clear()

$retval = $false
if ([string]::IsNullOrEmpty($ModuleName) )
{
return $retval
}
$error.Clear()

$cim = Get-Module -Name $ModuleName

########Check for powershell 1.0
if ($error.Count -ne 0)
{
if ($null -eq $error[0].Exception)
{
$error.Clear()
return $retval

}

$type = $error[0].Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
$error.Clear()
return $retval
}

$error.Clear()
}

if ($null -eq $cim)
{
Import-Module $ModuleName
if ($error.Count -eq 0)
{
$retval = $true
}

$error.Clear()
}
else
{
$retval = $true
}

return $retval

}

function Get-DispObjectName([string]$ObjectName,[string]$PostFix,[int]$MaxSize=4000)
{
$oLen = $ObjectName.Length
$pLen = $PostFix.Length
$delta1 = $pLen - $MaxSize
$delta = $delta1 + $oLen

$result = $ObjectName + $PostFix

if ($MaxSize -le 0) {return [string]::Empty;}

if ($delta -gt 0)
{
if($delta1 -lt 0)
{
$result = $ObjectName.Substring(0,-$delta1) + $PostFix
}
else
{
$result = $result.Substring(0,$MaxSize)
}
}

return $result
}



Function Discovery-Nodes
(
$oCluster,
[string]$ComputerName,
[string]$NetBiosName,
$oDiscoveryData,
$oClusterInstance
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = $true
$oNode = Get-ClusterNodes -oCluster $oCluster -ComputerName $ComputerName -NodeNameFilter $NetBiosName
if (0 -ne $error.Count)
{
return $false
}

if ($null -ne $oNode)
{
$result = WinClusterNodeDiscoverInstance $oCluster.Name $oNode $oDiscoveryData $ComputerName
if ($true -eq $result)
{
$result = WinClusterNodeDiscoverClusterContainsRelationship $ComputerName $oClusterInstance $oDiscoveryData
}
}

return $result
}

Function WinClusterNodeDiscoverInstance($hostKey, $oObject, $oDiscoveryData,$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$defaultValue = "0"

$NodeName = $oObject.Name
$description = $oObject.Description
$cSDVersion = $oObject.CSDVersion
$buildNumber = Convert-IntToString -Value $oObject.BuildNumber -DefaultValue $defaultValue
$majorVersion = Convert-IntToString -Value $oObject.MajorVersion -DefaultValue $defaultValue
$minorVersion = Convert-IntToString -Value $oObject.MinorVersion -DefaultValue $defaultValue
$nodeHighestVersion = Convert-IntToString -Value $oObject.NodeHighestVersion -DefaultValue $defaultValue
$nodeLowestVersion = Convert-IntToString -Value $oObject.NodeLowestVersion -DefaultValue $defaultValue

$Message = $StartNodeDiscoveryMessage -f $NodeName
LogMessage $DBG_TRACE $Message

$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Node']$")
if ($null -eq $oInstance)
{
$Message = $ErrorNodeDiscoveryMessage -f ($name, $ErrorNodeMessage)
LogMessage $DBG_ERROR $Message
return $false
}

$NodeNameTrim = Get-StringProperty -Property $NodeName -Trim $true
$oInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $ComputerName)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/ClusterName$", $hostKey)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeName$", $NodeNameTrim)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/Description$", $description)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/BuildNumber$", $buildNumber)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/CSDVersion$", $cSDVersion)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/MajorVersion$", $majorVersion)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/MinorVersion$", $minorVersion)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeHighestVersion$", $nodeHighestVersion)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Node']/NodeLowestVersion$", $nodeLowestVersion)

if (0 -ne $error.Count)
{
$Message = $ErrorNodeDiscoveryMessage -f ($NodeName, $ErrorNodeMessage)
LogMessage $DBG_ERROR $Message
return $false
}

$oDiscoveryData.AddInstance($oInstance)
if (0 -ne $error.Count)
{
$Message = $ErrorAddNodeDiscoveryMessage -f ($NodeName, $ErrorNodeMessage)
LogMessage $DBG_ERROR $Message

return $false
}

$result = WinClusterNodeDiscoverClusterNodeHostsNodeRoleRelationship $oObject $oDiscoveryData $ComputerName

return $result
}

Function WinClusterNodeDiscoverClusterNodeHostsNodeRoleRelationship(
$oObject,
$oDiscoveryData,
$ComputerName
)
{

LogMessage $DBG_TRACE $StartNodeHostingDiscoveryMessage
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result =$false
$oNodeRoleInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.NodeRole']$")
if ($null -eq $oNodeRoleInstance)
{
$args = "Microsoft.Windows.Cluster.NodeRole"
$Message = $ErrorNodeHostingDiscoveryMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}
$ObjectName = Get-StringProperty -Property $oObject.Name
$oNodeRoleInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$oNodeRoleInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $ObjectName)
$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Node']$")
if ($null -eq $oInstance)
{
$args = "Microsoft.Windows.Cluster.Node"
$Message = $ErrorNodeHostingDiscoveryMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}

$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$oRelationshipInstance = $oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='Windows!Microsoft.Windows.ComputerHostsComputerRole']$")
if ($null -eq $oRelationshipInstance)
{
$args = "Microsoft.Windows.Cluster.Node"
$Message = $ErrorNodeHostingRelDisMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}

$oRelationshipInstance.Source = $oInstance
$oRelationshipInstance.Target = $oNodeRoleInstance
$error.Clear()
$oDiscoveryData.AddInstance($oRelationshipInstance)
if (0 -ne $error.Count)
{
$Message = $ErrorAddNodeHostingDiscMessage -f $error[0].Exception.Message
LogMessage $DBG_ERROR $Message
return $false
}

$oDiscoveryData.AddInstance($oNodeRoleInstance)

$result = 0 -eq $Error.Count

return $result
}

Function WinClusterNodeDiscoverClusterContainsRelationship(
$ComputerName,
$oClusterInstance,
$oDiscoveryData
)
{

$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
LogMessage $DBG_TRACE $StartNodeContainsDiscRelMessage
$error.Clear()

$result = $false
$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Node']$")
if ($null -eq $oInstance)
{

$message = $ErrorNodeContainDiscRelsMsg -f $error[0].Exception.Message
LogMessage $DBG_ERROR $message
return $result
}

$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)

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

if ($false -eq $result)
{
$message = $ErrorNodeAddContainDiscRelMsg -f $error[0].Exception.Message
LogMessage $DBG_ERROR $message
}

return $result
}


Function Discovery-ClusterNetworks
(
$oCluster,
[string]$ComputerName,
[string]$NetBiosName,
$oDiscoveryData,
$oClusterInstance,
$NetworkInterfaceTypeGuid,
$NetworkContainsInterfaceGuid,
$networkInterfacePropClusterNameGuid,
$networkInterfacePropNameGuid,
$strNetworkInterfacePropClusterAdapterID,
$discoverUnusedNetworks,
[bool]$appendClusterNameToResourceGroup
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$DiscoveryError = 0
$DiscoveryDisabled = 2
$DiscoveryEnabled = 1

$DiscoveryResult = $true
$discoverUnusedNetworks = Convert-ToBoolean -sBool $discoverUnusedNetworks

$oNetworks = Get-ClusterNetworks -oCluster $oCluster -ComputerName $ComputerName
if ($null -eq $oNetworks -and 0 -ne $error.Count)
{
return $false
}

ForEach($oNetwork in $oNetworks)
{
$result = WinClusterNetworkDiscoverInstance -hostKey $oCluster.Name -oObject $oNetwork -oDiscoveryData $oDiscoveryData -ComputerName $ComputerName -NetBiosName $NetBiosName -discoverUnusedNetworks $discoverUnusedNetworks -NetworkInterfaceTypeGuid $NetworkInterfaceTypeGuid -networkInterfacePropClusterNameGuid $networkInterfacePropClusterNameGuid -networkInterfacePropNameGuid $networkInterfacePropNameGuid -strNetworkInterfacePropClusterAdapterID $strNetworkInterfacePropClusterAdapterID -NetworkContainsInterfaceGuid $NetworkContainsInterfaceGuid -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup

if ($DiscoveryError -eq $result)
{
$DiscoveryResult = $false
break
}
elseif( $DiscoveryDisabled -eq $result)
{
continue
}

$result = WinClusterNetworkDiscoverClusterContainsRelationship -oClusterInstance $oClusterInstance -hostKey $oCluster.Name -networkKey $oNetwork.Name -oDiscoveryData $oDiscoveryData

if ($false -eq $result)
{
$DiscoveryResult = $false
break
}

}

return $DiscoveryResult
}

Function WinClusterNetworkDiscoverClusterContainsRelationship(
$oClusterInstance,
$hostKey,
$networkKey,
$oDiscoveryData
)
{


LogMessage $DBG_TRACE $StartNetworkRelDiscoveryMessage
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Network']$")
if ($null -eq $oInstance)
{
$args = "Microsoft.Windows.Cluster.Network"
$Message = $ErrorNetworkRelDiscMessage -f $args
LogMessage $DBG_ERROR $Message
return $false
}

$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", $hostKey)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", $networkKey)
$result = DiscoverClusterContainsRelationship $oClusterInstance $oInstance "$MPElement[Name='Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Network']$" $oDiscoveryData

return $result
}

Function WinClusterNetworkDiscoverInstance(
$hostKey,
$oObject,
$oDiscoveryData,
$ComputerName,
$NetBiosName,
[bool]$discoverUnusedNetworks,
$NetworkInterfaceTypeGuid,
$networkInterfacePropClusterNameGuid,
$networkInterfacePropNameGuid,
$strNetworkInterfacePropClusterAdapterID,
$NetworkContainsInterfaceGuid,
[bool]$appendClusterNameToResourceGroup
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$DiscoveryError = 0
$DiscoveryDisabled = 2
$DiscoveryEnabled = 1

$role = $oObject.Role

$roleNone = ($role -eq "0") -or $true -eq [string]::IsNullOrEmpty($role)
If($discoverUnusedNetworks -eq $false -and $true -eq $roleNone)
{
return $DiscoveryDisabled
}

$address = $oObject.Address
$addressMask = $oObject.AddressMask
$description = $oObject.Description
$ObjectName = $oObject.Name
$oInstance = WinClusterObjectDiscoverInstance $hostKey $ObjectName "$MPElement[Name='Microsoft.Windows.Cluster.Network']$" $oDiscoveryData $appendClusterNameToResourceGroup

if ($null -eq $oInstance)
{
return $DiscoveryError
}

$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Network']/Address$", $address)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Network']/AddressMask$", $addressMask)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Network']/Description$", $description)

if (0 -ne $error.Count)
{
return $DiscoveryError
}

$oDiscoveryData.AddInstance($oInstance)
if (0 -ne $error.Count)
{
return $DiscoveryError
}

if ([string]::IsNullOrEmpty($NetworkInterfaceTypeGuid))
{
return $DiscoveryEnabled
}

#====================================================
# discover contains network interfaces
#====================================================
$oNetworkItfs = Get-ClusterNetworkInterfaceFromNet -oNet $oObject -ComputerName $ComputerName
if (0 -ne $error.Count)
{
return $DiscoveryError
}

ForEach($oNetworkItf in $oNetworkItfs)
{
$baseOSItfName = Get-NetIfName $oNetworkItf
if(-Not ($oNetworkItf.SystemName -ieq $NetBiosName) -or [string]::IsNullOrEmpty($baseOSItfName))
{
continue
}

$deviceID = WinClusterNetworkInterfaceDiscoverInstance -clusterKey $hostKey -networkItfKey $baseOSItfName -oObject $oNetworkItf -oDiscoveryData $oDiscoveryData -discoverUnusedNetworks $discoverUnusedNetworks -ComputerName $ComputerName -networkInterfaceTypeGuid $NetworkInterfaceTypeGuid -networkInterfacePropClusterNameGuid $networkInterfacePropClusterNameGuid -networkInterfacePropNameGuid $networkInterfacePropNameGuid -strNetworkInterfacePropClusterAdapterID $strNetworkInterfacePropClusterAdapterID
if ($null -eq $deviceID)
{
if (0 -eq $error.Count)
{
continue
}
else
{
return $DiscoveryError
}
}

# discover that network contains interfaces
$result = WinClusterNetworkDiscoverContainsNetworkInterfacesRelationship -hostKey $hostKey -networkKey $ObjectName -networkItfKey $deviceID -oRealNetworkItf $oNetworkItf -oDiscoveryData $oDiscoveryData -ComputerName $ComputerName -NetworkInterfaceTypeGuid $NetworkInterfaceTypeGuid -NetworkContainsInterfaceGuid $NetworkContainsInterfaceGuid

if ($false -eq $result )
{
return $DiscoveryError
}
}

return $DiscoveryEnabled
}
#==========================================================================
# Discover cluster containing network interfaces relationship instance
#==========================================================================
Function WinClusterNetworkDiscoverContainsNetworkInterfacesRelationship(
$hostKey,
$networkKey,
$networkItfKey,
$oRealNetworkItf,
$oDiscoveryData,
$ComputerName,
$NetworkInterfaceTypeGuid,
$NetworkContainsInterfaceGuid
)
{

$result = $false
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
LogMessage $DBG_TRACE $StartNetworkIfRelDiscoveryMessage
$error.Clear()

$oNetworkInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Network']$")
if ($null -eq $oNetworkInstance)
{
$args = "Microsoft.Windows.Cluster.Network"
$Message = $ErrorNetIfRelDiscoveryMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}

$networkKey = Get-StringProperty -Property $networkKey -MaxSize $ObjectNameStringMaxSize -Trim $true

$oNetworkInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$",$hostKey)
$oNetworkInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$",$networkKey)
$oInstance = $oDiscoveryData.CreateClassInstance($NetworkInterfaceTypeGuid)
if ($null -eq $oInstance)
{
$args = "Network Interface"
$Message = $ErrorNetIfRelDiscoveryMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}

$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$",$ComputerName)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$",$networkItfKey)
$oRelationshipInstance = $oDiscoveryData.CreateRelationshipInstance($NetworkContainsInterfaceGuid)
if ($null -eq $oRelationshipInstance)
{
$args = "Network Interface"
$Message = $ErrorNetIfRelDisMessage -f $args
LogMessage $DBG_ERROR $Message

return $false
}


$oRelationshipInstance.Source = $oNetworkInstance
$oRelationshipInstance.Target = $oInstance
$oDiscoveryData.AddInstance($oRelationshipInstance)
$result = 0 -eq $error.Count

if ($false -eq $result)
{
$args = "Network to Network Interface RelationShip"
$Message = $ErrorAddNetIfRelDiscMessage -f $args
LogMessage $DBG_ERROR $Message


}

return $result
}

Function WinClusterNetworkInterfaceDiscoverInstance(
$clusterKey,
$networkItfKey,
$oObject,
$oDiscoveryData,
$discoverUnusedNetworks,
$ComputerName,
$networkInterfaceTypeGuid,
$networkInterfacePropClusterNameGuid,
$networkInterfacePropNameGuid,
$strNetworkInterfacePropClusterAdapterID
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$message = "Creating DiscoveryData packet for " + $networkInterfaceTypeGuid
LogMessage $DBG_TRACE $message
$error.Clear()

$NicData = Get-NicData -ComputerName $ComputerName -NetId $networkItfKey -oObject $oObject -discoverUnusedNetworks $discoverUnusedNetworks
$deviceID = $NicData["deviceID"]
if ($null -eq $deviceID)
{
return $deviceID
}

$oInstance = $oDiscoveryData.CreateClassInstance($networkInterfaceTypeGuid)
if (0 -ne $error.Count -or $null -eq $oInstance)
{
return $null
}

$adapterType = $NicData["adapterType"]
$index = $NicData["index"]
$manufacturer = $NicData["manufacturer"]
$macAddress = $NicData["macAddress"]
$serviceName = $NicData["serviceName"]
$adapter = $oObject.Adapter
$address = $oObject.Address
$description = $oObject.Description
$name = $oObject.DeviceID
$strClusterAdapterID = $oObject.AdapterId
if ([string]::IsNullOrEmpty($description))
{
$description = $adapter
}

if ([string]::IsNullOrEmpty($strClusterAdapterID))
{
$strClusterAdapterID = ""
}
else
{
$strClusterAdapterID = $strClusterAdapterID.Replace("{", "").Replace("}", "")
}

$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$oInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $networkItfKey)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Name$", $adapter)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", $deviceID)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", $description)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/IPAddress$", $address)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/AdapterType$", $adapterType)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Index$", $index)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Manufacturer$", $manufacturer)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/MACAddress$", $macAddress)
$oInstance.AddProperty("$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/ServiceName$", $serviceName)
if(-Not [string]::IsNullOrEmpty($networkInterfacePropClusterNameGuid) )
{
$oInstance.AddProperty($networkInterfacePropClusterNameGuid, $clusterKey)
}

if(-Not [string]::IsNullOrEmpty($networkInterfacePropNameGuid) )
{
$oInstance.AddProperty($networkInterfacePropNameGuid, $name)
}


if(-Not [string]::IsNullOrEmpty($strNetworkInterfacePropClusterAdapterID) )
{
$oInstance.AddProperty($strNetworkInterfacePropClusterAdapterID, $strClusterAdapterID)
}

if (0 -ne $error.Count)
{
return $null
}

$oDiscoveryData.AddInstance($oInstance)
if (0 -ne $error.Count)
{
$deviceID = $null
}

return $deviceID;
}

#============================================================
# Get Network Name from DeviceId
# OS &lt; 2008
# DeviceId=NetName - SystemName
# OS &gt;= 2008
# DeviceId=SystemName - NetName
#===========================================================
Function Get-NetIfName($oNetworkItf)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = ""
$systemName = $oNetworkItf.SystemName
$deviceId = $oNetworkItf.DeviceID

if ([string]::IsNullOrEmpty($systemName) -or [string]::IsNullOrEmpty($deviceId) )
{
return $result
}

if ($deviceId.Length -le ($systemName.Length + 3) -or $deviceId.Length -le 3)
{
return $result
}

$delta = $deviceId.Length - $systemName.Length
$rp = $deviceId.Substring($delta,$systemName.Length)
$lp = $deviceId.Substring(0, $systemName.Length)
$delta = $delta -3

if ($systemName -eq $lp)
{
$result = $deviceId.Substring($systemName.Length + 3,$delta)
}
elseif($systemName -eq $rp){
$result = $deviceId.Substring(0,$delta)
}

return $result
}




Function Discovery-ClusterGroup(
$oCluster,
[string]$ComputerName,
[string]$NetBiosName,
$oDiscoveryData,
$ResourceGroupDiscoveryLimit,
$ClusterName,
$GroupFilter,
$discoverNonCSVResources,
$discoverCSVResources,
$oClusterInstance,
[bool]$appendClusterNameToResourceGroup
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$oGroups = Get-ClusterGroups -oCluster $oCluster -ComputerName $ComputerName
if (0 -ne $error.Count)
{
$message = $ClusterGroupGetErrorMessage -f $oCluster.Name
$message = $message +" Error:" + $error[0].Exception.Message
LogMessage $DBG_ERROR $message $Message
return $false
}

$ActiveNodes = Get-GroupsToActiveNode -oCluster $oCluster -ComputerName $ComputerName

if (0 -ne $error.Count -or 0 -eq $ActiveNodes.Count)
{
$Message = $ClusterGroupGetActiveNodeErrorMessage -f $oCluster.Name
$message = $message +" Error:" + $error[0].Exception.Message
LogMessage $DBG_ERROR $message $Message
return $false
}

$result = Discovery-Groups -ResourceGroupDiscoveryLimit $ResourceGroupDiscoveryLimit -ComputerName $ComputerName -ClusterName $ClusterName -oGroups $oGroups -GroupFilter $GroupFilter -oDiscoveryData $oDiscoveryData -ActiveNodes $ActiveNodes -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -NetBiosName $NetBiosName -oClusterInstance $oClusterInstance -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup
return $result
}

Function Discovery-Groups(
$ResourceGroupDiscoveryLimit,
[string]$ComputerName,
[string]$ClusterName,
$oGroups,
$GroupFilter,
$oDiscoveryData,
[HashTable]$ActiveNodes,
[bool]$discoverNonCSVResources,
[bool]$discoverCSVResources
,[string]$NetBiosName,
$oClusterInstance
,[bool]$appendClusterNameToResourceGroup
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = $true
$iGroupCounter = 0
ForEach($oGroup in $oGroups)
{
$GroupType = Get-ResourceGroupType -oGroup $oGroup
$IsDiscoveryEnabled = Discovery-IsEnabledGroup -oGroup $oGroup -GroupTypeFilter $GroupFilter -GroupType $GroupType

If ($false -eq $IsDiscoveryEnabled)
{
continue
}

$iGroupCounter++
# resource group discover limit exceeded?
If($iGroupCounter -gt $ResourceGroupDiscoveryLimit)
{
$message = $ErrorClusterGroupResourceLimit -f ($ClusterName, $iGroupCounter,$ResourceGroupDiscoveryLimit)
LogMessage $DBG_WARNING $message 7010
break
}

$result = Discovery-Group -ComputerName $ComputerName -ClusterName $ClusterName -oGroup $oGroup -oDiscoveryData $oDiscoveryData -ActiveNodes $ActiveNodes -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -NetBiosName $NetBiosName -oClusterInstance $oClusterInstance -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup -GroupType $GroupType
if ($false -eq $result)
{
break
}
}

return $result
}

Function Discovery-IsEnabledGroup($oGroup,$GroupTypeFilter,$GroupType)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = $true
if ($null -eq $oGroup)
{
return $false
}

if ($null -eq $GroupType -or $null -eq $GroupTypeFilter)
{
return $result
}

$subresult = $GroupTypeFilter.Contains($GroupType)
if (0 -eq $error.Count)
{
$result = -Not $subresult
}

$error.Clear()

return $result

}


Function Discovery-Group(
[string]$ComputerName
,[string]$ClusterName
,$oGroup
,$oDiscoveryData
,[HashTable]$ActiveNodes
,[bool]$discoverNonCSVResources
,[bool]$discoverCSVResources
,[string]$NetBiosName
,$oClusterInstance
,[bool]$appendClusterNameToResourceGroup
,$GroupType

)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$defaultValue = "-1"
$GroupName = $oGroup.Name
if($true -eq [string]::IsNullOrEmpty($GroupName) )
{
return $false
}

$autoFailbackType = $oGroup.AutoFailbackType
$description = $oGroup.Description
$failbackWindowEnd = $oGroup.FailbackWindowEnd
$failoverPeriod = $oGroup.FailoverPeriod
$persistentState = $oGroup.PersistentState
$failbackWindowStart = $oGroup.FailbackWindowStart
$failoverThreshold = $oGroup.FailoverThreshold #int uint32

$failbackWindowStart = Convert-IntToString -Value $failbackWindowStart -DefaultValue $defaultValue
$failbackWindowEnd = Convert-IntToString -Value $failbackWindowEnd -DefaultValue $defaultValue

$failoverPeriod = Convert-IntToString -Value $failoverPeriod -DefaultValue "-1"
$failoverThreshold = Convert-IntToString -Value $failoverThreshold -DefaultValue "-1"
$autoFailbackType = Convert-IntToString -Value $autoFailbackType -DefaultValue "-1"

$result = Discover-ClusterGroupInstance -hostKey $ClusterName -GroupName $GroupName -oGroup $oGroup -autoFailbackType $autoFailbackType -description $description -failbackWindowEnd $failbackWindowEnd -failbackWindowStart $failbackWindowStart -failoverPeriod $failoverPeriod -failoverThreshold $failoverThreshold -persistentState $persistentState -oDiscoveryData $oDiscoveryData -ActiveNodes $ActiveNodes -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -GroupType $GroupType -NetBiosName $NetBiosName -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup
if ($false -eq $result)
{
return $result
}

#cluster contains groups

$result = Discover-ClusterContainsGroupRelationship -oClusterInstance $oClusterInstance -hostKey $ClusterName -groupKey $GroupName -oDiscoveryData $oDiscoveryData
if ($false -eq $result)
{
return $result
}


$result = Discover-HostedGroupWithClusterResources -ComputerName $ComputerName -hostKey $ClusterName -GroupName $GroupName -oGroup $oGroup -autoFailbackType $autoFailbackType -description $description -failbackWindowEnd $failbackWindowEnd -failbackWindowStart $failbackWindowStart -failoverPeriod $failoverPeriod -failoverThreshold $failoverThreshold -persistentState $persistentState -oDiscoveryData $oDiscoveryData -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -GroupType $GroupType -NetBiosName $NetBiosName
if ($false -eq $result)
{
return $result
}

# group contains hosted group
$result = Discover-ClusterGroupContainsHostedGroupRelationship -hostKey $ClusterName -groupKey $GroupName -oDiscoveryData $oDiscoveryData -NetBiosName $NetBiosName -ComputerName $ComputerName

return $result
}


#================================================
#Add Group Discovery
#================================================
Function Discover-ClusterGroupInstance(
$hostKey
,$GroupName
,$autoFailbackType
,$description
,$failbackWindowEnd
,$failbackWindowStart
,$failoverPeriod
,$failoverThreshold
,$persistentState
,$oDiscoveryData
,[HashTable]$ActiveNodes
,[string]$NetBiosName
,[bool]$appendClusterNameToResourceGroup

)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()
$result = $false

$TrimGroupName = Get-StringProperty -Property $GroupName -Trim $true -MaxSize $ObjectNameStringMaxSize

If([string]::IsNullOrEmpty($TrimGroupName))
{
return $result
}

if ($null -ne $ActiveNodes)
{
$NodeName = $ActiveNodes[$GroupName]
}

If([string]::IsNullOrEmpty($NodeName))
{
$NodeName = $NetBiosName
}

$error.Clear()
$discoveryClass = "$MPElement[Name='Microsoft.Windows.Cluster.Group']$"

$oInstance = WinClusterObjectDiscoverInstance -hostkey $hostKey -ObjectName $GroupName -discoveryClass $discoveryClass -oDiscoveryData $oDiscoveryData -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup

if ($null -eq $oInstance)
{
return $result
}

$GroupName = Get-StringProperty -Property $GroupName -MaxSize $ObjectNameStringMaxSize
$error.Clear()

$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/OriginalGroupName$", $GroupName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/AutoFailbackType$", $autoFailbackType)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/Description$", $description)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailbackWindowEnd$", $failbackWindowEnd)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailbackWindowStart$", $failbackWindowStart)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailoverPeriod$", $failoverPeriod)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/FailoverThreshold$", $failoverThreshold)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/PersistentState$", $persistentState)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$", $NodeName)

if (0 -ne $error.Count)
{
return $result
}

$oDiscoveryData.AddInstance($oInstance)
$result = 0 -eq $error.Count


return $result
}

#==========================================================================
# Discover cluster contains relationship instance
#==========================================================================
Function Discover-ClusterGroupContainsHostedGroupRelationship(
$hostKey
,$groupKey
,$oDiscoveryData
,$NetBiosName
,$ComputerName

)
{

LogMessage $DBG_TRACE "Creating DiscoveryData packet for cluster group contains hosted groups."
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()
$result = $false

$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Group']$")
if ($null -eq $oInstance)
{
return $result
}

$groupkey = Get-StringProperty -Property $groupkey -MaxSize $ObjectNameStringMaxSize -Trim $true

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

if (0 -ne $error.Count)
{
return $result
}


$oHostedInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$")
if ($null -eq $oHostedInstance)
{
return $result
}

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

if (0 -ne $error.Count)
{
return $result
}

$oRelationshipInstance = $oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Cluster.Group.Contains.Microsoft.Windows.Cluster.HostedGroup']$")
if ($null -eq $oRelationshipInstance)
{
return $result
}

$oRelationshipInstance.Source = $oInstance
$oRelationshipInstance.Target = $oHostedInstance

if (0 -ne $error.Count)
{
return $result
}

$oDiscoveryData.AddInstance($oRelationshipInstance)
$result = 0 -eq $error.Count

return $result
}


#==========================================================================
# Discover cluster contains relationship instance
#==========================================================================
Function Discover-ClusterContainsGroupRelationship(
$oClusterInstance
,$hostKey
,$groupKey
,$oDiscoveryData

)
{

LogMessage $DBG_TRACE "Creating DiscoveryData packet for cluster contains groups."
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()
$result = $false

$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Group']$")
if ($null -eq $oInstance)
{
return $result
}

$groupKey = Get-StringProperty -Property $groupkey -MaxSize $ObjectNameStringMaxSize -Trim $true

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

if (0 -ne $error.Count)
{
return $result
}

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

return $result
}

#==========================================================================
# Discover cluster node hosted group
#==========================================================================
Function Discover-HostedGroup(
$hostKey,
$oObject,
$autoFailbackType,
$description,
$failbackWindowEnd,
$failbackWindowStart,
$failoverPeriod,
$failoverThreshold,
$persistentState,
$oDiscoveryData,
$NetBiosName,
$ComputerName

)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()
$result = $false


# instance
$oHostedGroupInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$")
if ($null -eq $oHostedGroupInstance)
{
return $result
}

$GroupName = $oObject.Name
$GroupName = Get-StringProperty -Property $GroupName -MaxSize $ObjectNameStringMaxSize
$TrimGroupName = Get-StringProperty -Property $GroupName -MaxSize $ObjectNameStringMaxSize -Trim $true
$description = Get-StringProperty -Property $description
$failbackWindowEnd = Get-StringProperty -Property $failbackWindowEnd
$failbackWindowStart = Get-StringProperty -Property $failbackWindowStart

$displayName = " (" + $hostKey +" )" +" (" + $NetBiosName + ")"

$displayName = Get-DispObjectName -ObjectName $GroupName -PostFix $displayName

$oHostedGroupInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $displayName)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$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$", $TrimGroupName)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/EscapedGroupName$", $GroupName)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/AutoFailbackType$", $autoFailbackType)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/Description$", $description)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowEnd$", $failbackWindowEnd)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowStart$", $failbackWindowStart)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailoverPeriod$", $failoverPeriod)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/FailoverThreshold$", $failoverThreshold)
$oHostedGroupInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/PersistentState$", $persistentState)

if (0 -ne $error.Count)
{
return $result
}

$oDiscoveryData.AddInstance($oHostedGroupInstance)
$result = 0 -eq $error.Count

return $result

}

Function Discover-HostedGroupWithClusterResources
(
$ComputerName
,$hostKey
,$GroupName
,$oGroup
,$autoFailbackType
,$description
,$failbackWindowEnd
,$failbackWindowStart
,$failoverPeriod
,$failoverThreshold
,$persistentState
,$oDiscoveryData
,[bool]$discoverNonCSVResources
,[bool]$discoverCSVResources
,$GroupType
,[string]$NetBiosName

)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$result = Discover-HostedGroup -hostKey $hostKey -oObject $oGroup -autoFailbackType $autoFailbackType -description $description -failbackWindowEnd $failbackWindowEnd -failbackWindowStart $failbackWindowStart -failoverPeriod $failoverPeriod -failoverThreshold $failoverThreshold -persistentState $persistentState -oDiscoveryData $oDiscoveryData -NetBiosName $NetBiosName -ComputerName $ComputerName

if ($false -eq $result)
{
return $result
}

$result = Discover-AllClusterResources -hostkey $hostKey -GroupName $GroupName -oGroup $oGroup -GroupType $GroupType -oDiscoveryData $oDiscoveryData -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -ComputerName $ComputerName -NetBiosName $NetBiosName

return $result

}


#====================================================
# discover resources
#====================================================

Function Discover-AllClusterResources
(
$hostkey
,$GroupName
,$oGroup
,$GroupType
,$oDiscoveryData
,[bool]$discoverNonCSVResources
,[bool]$discoverCSVResources
,[string]$ComputerName
,[string]$NetBiosName

)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$result = Discovery-ClusterResources -ComputerName $ComputerName -IsDiscoveryEnabled $discoverNonCSVResources -hostKey $hostKey -GroupName $GroupName -oGroup $oGroup -oDiscoveryData $oDiscoveryData -NetBiosName $NetBiosName -GroupType $GroupType
if ($false -eq $result)
{
return $result
}

$result = Discovery-ClusterResources -ComputerName $ComputerName -IsDiscoveryEnabled $discoverCSVResources -IsCSV $true -hostKey $hostKey -GroupName $GroupName -oGroup $oGroup -oDiscoveryData $oDiscoveryData -NetBiosName $NetBiosName -GroupType $GroupType

return $result


}

Function Discovery-ClusterResources
(
[string]$ComputerName
,[bool]$IsDiscoveryEnabled
,[bool]$IsCSV = $false
,$hostKey
,[string]$GroupName
,$oGroup
,$oDiscoveryData
,$NetBiosName
,$GroupType
)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$result = $false
if ($false -eq $IsDiscoveryEnabled)
{
return $true
}

if ($true -eq $IsCSV)
{
if ($null -eq $GroupType)
{
if ($GroupName -ne "Cluster Group")
{
return $true
}
}
else
{
if (1 -ne $GroupType)
{
return $true
}
}

$oResources = Get-CsvResourcesInGroup -oGroup $oGroup -ComputerName $ComputerName
}
else
{
$oResources = Get-ClusterResourceInGroup -oGroup $oGroup -ComputerName $ComputerName
}

if (0 -ne $error.Count)
{
return $result
}

$result = $true
ForEach($oResource in $oResources)
{
$ResourceName = $oResource.Name
If ([string]::IsNullOrEmpty($ResourceName))
{
continue
}
#Discover Resource

$result = Discover-ClusterResourceInstance -clusterKey $hostKey -groupKey $GroupName -oObject $oResource -oDiscoveryData $oDiscoveryData -NetBiosName $NetBiosName -ComputerName $ComputerName

if($false -eq $result)
{
break
}


}

return $result
}

Function Discover-ClusterResourceInstance(
$clusterKey,
$groupKey,
$oObject,
$oDiscoveryData,
$NetBiosName,
$ComputerName
)
{
LogMessage $DBG_TRACE "Creating DiscoveryData packet for Microsoft.Windows.Cluster.Resource."
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()
$result = $false


$oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Resource']$")
if ($null -eq $oInstance)
{
return $result
}


$ResourceName = $oObject.Name
$typeName = $oObject.Type
$description = $oObject.Descriptions
$defaultValue = "-1"
$isAlivePollInterval = Convert-IntToString -Value $oObject.IsAlivePollInterval -DefaultValue $defaultValue
$looksAlivePollInterval = Convert-IntToString -Value $oObject.LooksAlivePollInterval -DefaultValue $defaultValue
$pendingTimeout = Convert-IntToString -Value $oObject.PendingTimeout -DefaultValue $defaultValue
$persistentState = Convert-ToBoolean -sBool $oObject.PersistentState
$restartAction = Convert-IntToString -Value $oObject.RestartAction -DefaultValue $defaultValue
$restartPeriod = Convert-IntToString -Value $oObject.RestartPeriod -DefaultValue $defaultValue
$restartThreshold = Convert-IntToString -Value $oObject.RestartThreshold -DefaultValue $defaultValue
$retryPeriodOnFailure = Convert-IntToString -Value $oObject.RetryPeriodOnFailure -DefaultValue $defaultValue
$separateMonitor = Convert-ToBoolean -sBool $oObject.SeparateMonitor

$groupKey = Get-StringProperty -Property $groupKey -MaxSize $ObjectNameStringMaxSize -Trim $true
$DispName = Get-StringProperty -Property $ResourceName -MaxSize $ObjectNameStringMaxSize
$EsResourceName = $DispName
$ResourceName = Get-StringProperty -Property $ResourceName -MaxSize $ObjectNameStringMaxSize -Trim $true
$typeName = Get-StringProperty -Property $typeName
$description = Get-StringProperty -Property $description

$oInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $DispName)
$oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $ComputerName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", $clusterKey)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", $NetBiosName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", $groupKey)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceName$", $ResourceName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/EscapedResourceName$",$EsResourceName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/ResourceTypeName$", $typeName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/Description$", $description)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/IsAlivePollInterval$", $isAlivePollInterval)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/LooksAlivePollInterval$", $looksAlivePollInterval)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/PendingTimeout$", $pendingTimeout)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/PersistentState$", $persistentState)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartAction$", $restartAction)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartPeriod$", $restartPeriod)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RestartThreshold$", $restartThreshold)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/RetryPeriodOnFailure$", $retryPeriodOnFailure)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Resource']/SeparateMonitor$", $separateMonitor)#

if (0 -ne $error.Count)
{
return $result
}

$oDiscoveryData.AddInstance($oInstance)
$result = 0 -eq $error.Count

return $result
}


#==========================================================================
# Discover cluster classes
#==========================================================================
Function WinClusterDiscover(
$oDiscoveryData
,$ComputerName
,$NetBiosName
,$NetworkInterfaceTypeGuid
,$NetworkContainsInterfaceGuid
,$networkInterfacePropClusterNameGuid
,$networkInterfacePropNameGuid
,$strNetworkInterfacePropClusterAdapterID
,$discoverUnusedNetworks
,$ResourceGroupDiscoveryLimit
,$GroupFilter
,[bool]$discoverNonCSVResources
,[bool]$discoverCSVResources
,[bool]$appendClusterNameToResourceGroup
,$useCIm
)
{
$result = $true
$oClusters = Get-WinClusters -computerName $ComputerName -UseCim $useCim
if (0 -ne $error.Count)
{
$result = Check-WmiExceptions -Exception $error[0].Exception
return $result
}

ForEach($oCluster in $oClusters)
{
$oClusterInstance = Discover-Cluster -ClusterName $oCluster.Name -oDiscoveryData $oDiscoveryData
if ($null -eq $oClusterInstance)
{
$result = $false
break
}

$result = Discovery-Nodes -oCluster $oCluster -ComputerName $ComputerName -NetBiosName $NetBiosName -oDiscoveryData $oDiscoveryData -oClusterInstance $oClusterInstance
if ($false -eq $result)
{
$message = $ErrorClNodesDiscMessage -f ($oCluster.Name,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message
break
}

# networks
$result = Discovery-ClusterNetworks -oCluster $oCluster -ComputerName $ComputerName -NetBiosName $NetbiosName -oDiscoveryData $oDiscoveryData -oClusterInstance $oClusterInstance -NetworkInterfaceTypeGuid $NetworkInterfaceTypeGuid -NetworkContainsInterfaceGuid $NetworkContainsInterfaceGuid -networkInterfacePropClusterNameGuid $networkInterfacePropClusterNameGuid -networkInterfacePropNameGuid $networkInterfacePropNameGuid -strNetworkInterfacePropClusterAdapterID $strNetworkInterfacePropClusterAdapterID -discoverUnusedNetworks $discoverUnusedNetworks -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup
if ($false -eq $result)
{
$message = $ErrorClNetworkDiscMessage -f ($oCluster.Name,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message

break
}

# groups
$result = Discovery-ClusterGroup -oCluster $oCluster -ComputerName $ComputerName -NetBiosName $NetBiosName -oDiscoveryData $oDiscoveryData -ResourceGroupDiscoveryLimit $ResourceGroupDiscoveryLimit -ClusterName $oCluster.Name -GroupFilter $GroupFilter -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -oClusterInstance $oClusterInstance -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup
if ($false -eq $result)
{
$message = $ErrorClGrpsDiscMessage -f ($oCluster.Name,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message

break
}

}

return $result

}

#==========================================================================
# Discover cluster contains relationship instance
#==========================================================================
Function DiscoverClusterContainsRelationship(
$oSourceInstance,
$oTargetInstance,
$discoveryRelationshipClass,
$oDiscoveryData
)
{
LogMessage $DBG_TRACE "Creating DiscoveryData packet for cluster contains objects."
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$result = $false

$oRelationshipInstance = $oDiscoveryData.CreateRelationshipInstance($discoveryRelationshipClass)
if ($null -eq $oRelationshipInstance)
{
return $result
}

$oRelationshipInstance.Source = $oSourceInstance
$oRelationshipInstance.Target = $oTargetInstance


$oDiscoveryData.AddInstance($oRelationshipInstance)
$result = 0 -eq $error.Count

return $result
}

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

#==========================================================================
# Discover instance
#==========================================================================
Function WinClusterObjectDiscoverInstance($hostKey, $ObjectName, $discoveryClass, $oDiscoveryData,[bool]$appendClusterNameToResourceGroup)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$message = $StartWinClusterInstDiscoveryMsg -f $discoveryClass
LogMessage $DBG_TRACE $message
$error.Clear()

$oInstance = $oDiscoveryData.CreateClassInstance($discoveryClass)
if ($null -eq $oInstance)
{
$message = $ErrorWinClusterInstDiscoveryMsg -f ($discoveryClass,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message
return $null
}

$displayname = " (" + $hostKey + ")"

If(($discoveryClass -eq "$MPElement[Name='Microsoft.Windows.Cluster.Group']$") -and ($appendClusterNameToResourceGroup -eq $true))
{

$displayName = Get-DispObjectName -ObjectName $ObjectName -PostFix $displayName


}
else
{
$displayName = Get-StringProperty -Property $ObjectName -MaxSize $ObjectNameStringMaxSize
}

$sName = Get-StringProperty -Property $ObjectName -MaxSize $ObjectNameStringMaxSize -Trim $true

$oInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $displayName)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ClusterName$", $hostKey)
$oInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectName$", $sName)


return $oInstance
}
# WinClusterObject

Function Discover-Cluster([string]$ClusterName,$oDiscoveryData)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$message = $StartWinClusterDiscoveryMsg -f $ClusterName
LogMessage $DBG_TRACE $message
$error.Clear()

$oClusterInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Cluster!Microsoft.Windows.Cluster']$")
if ($null -eq $oClusterInstance -or 0 -ne $error.Count)
{
$message = $ErrorWinClusterDiscoveryMsg -f ($ClusterName,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message
return $null
}

$oClusterInstance.AddProperty("$MPElement[Name='Cluster!Microsoft.Windows.Cluster']/Name$", $ClusterName)
if ( 0 -ne $error.Count)
{
$message = $ErrorSaveClusterDiscoveryMsg -f ($ClusterName,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message
return $null
}

$oDiscoveryData.AddInstance($oClusterInstance)
$result = 0 -eq $error.Count

if ($false -eq $result)
{
$oClusterInstance = $null
$message = $ErrorAddClusterDiscoveryMsg -f ($ClusterName,$error[0].Exception.Message)
LogMessage $DBG_ERROR $message

}

return $oClusterInstance
}



#==========================================================================
# FUNCTIONS
#==========================================================================

Function DiscoverInstances
(
$ComputerName
,$NetBiosName
,$NetworkInterfaceTypeGuid
,$NetworkContainsInterfaceGuid
,$networkInterfacePropClusterNameGuid
,$networkInterfacePropNameGuid
,$strNetworkInterfacePropClusterAdapterID
,$discoverUnusedNetworks
,$ResourceGroupDiscoveryLimit
,$GroupFilter
,[bool]$discoverNonCSVResources
,[bool]$discoverCSVResources
,[bool]$appendClusterNameToResourceGroup
,$OSVersion
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
Log-DiscoveryMessage -message $StartDiscoveryMsg
$error.Clear()
$oDiscoveryData = $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)

If(0 -ne $error.Count -or [string]::IsNullOrEmpty($oDiscoveryData))
{
LogMessage $DBG_ERROR $CreateDiscoveryDataErrorMsg + " Error: " + $error[0].Exception.Message

return $null
}

$useCim = CheckCmdLets
$result = Get-SnapshotDiscovery -OsVersion $OsVersion -useCim $useCim

if ($Exit_IncrementalDiscovery -eq $result)
{
$oDiscoveryData.IsSnapshot = $false
}
elseif($Start_SnapShotDiscovery -eq $result)
{

$result = WinClusterDiscover -oDiscoveryData $oDiscoveryData -ComputerName $ComputerName -NetBiosName $NetBiosName -NetworkInterfaceTypeGuid $NetworkInterfaceTypeGuid -NetworkContainsInterfaceGuid $NetworkContainsInterfaceGuid -networkInterfacePropClusterNameGuid $networkInterfacePropClusterNameGuid -networkInterfacePropNameGuid $networkInterfacePropNameGuid -strNetworkInterfacePropClusterAdapterID $strNetworkInterfacePropClusterAdapterID -discoverUnusedNetworks $discoverUnusedNetworks -ResourceGroupDiscoveryLimit $ResourceGroupDiscoveryLimit -GroupFilter $GroupFilter -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup -useCim $useCim

if ($false -eq $result)
{
$oDiscoveryData = Get-EmptyDiscoveryData -SourceId $SourceId -ManagedEntityId $ManagedEntityId -IsSnapshot $false
}

}

Log-DiscoveryMessage -message $FinishDiscoveryMsg
return $oDiscoveryData
}

function Get-EmptyDiscoveryData($SourceId, $ManagedEntityId,$IsSnapshot)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$Error.Clear()

if ($null -eq $oAPI)
{
$oAPI = New-Object -ComObject "MOM.ScriptAPI"
if ($null -eq $oAPI)
{
return $null
}
}

$Error.Clear()

$oDiscoveryDataTmp= $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
$oDiscoveryDataTmp.IsSnapshot = $IsSnapshot

return $oDiscoveryDataTmp
}

Function Get-OsFilter([string]$OSVersion,[string]$delimiter=",")
{
$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()

$Filter = "ProductType != 1"

if([string]::IsNullOrEmpty($OsVersion))
{
return $Filter
}
$prefix = " and (Version like '"
$separator = "%' or Version like '"
$EndClause = "%')"

$OsVersions = $OSVersion.Split($delimiter,[StringSplitOptions]::RemoveEmptyEntries)
if ($OsVersions.Count -eq 0 -or $null -eq $OsVersions )
{
return $Filter
}

$SubFilter = [string]::Join($separator,$OsVersions)
$Filter = $Filter + $prefix + $SubFilter + $EndClause

return $Filter
}

Function Get-SnapshotDiscovery($OsVersion,$useCim)
{
$ErrorActionPreference = "SilentlyContinue"

if([string]::IsNullOrEmpty($OsVersion))
{
return $Start_SnapShotDiscovery
}

$Filter = Get-OsFilter -OSVersion $OsVersion
$Error.Clear()

if ($true -eq $useCim)
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$result = Get-CimInstance -CimSession $cimsession -ClassName "Win32_OperatingSystem" -Property ("Version") -Filter $Filter
}
catch
{
$result = Get-WMIObject -ClassName "Win32_OperatingSystem" -Property ("Version") -Filter $Filter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}

if (0 -ne $Error.Count)
{
return $Exit_IncrementalDiscovery
}

}
else
{
$result = Get-WmiObject -Class "Win32_OperatingSystem" -Property ("Version") -Filter $Filter
if(0 -ne $Error.Count)
{
return $Exit_IncrementalDiscovery
}
}

if ($null -eq $result)
{
$result = $Exit_SnapShotDiscovery
}
else
{
$result = $Start_SnapShotDiscovery
}

return $result
}

Function Log-DiscoveryMessage([string]$message)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$timex=get-date -displayhint time
$message = $message +" " + $timex
LogMessage $DBG_TRACE $message

}

#==========================================================================
# Initialize the arguments in Script
#==========================================================================
Function Initialize-DiscoveryScript
(
[ref]$appendClusterNameToResourceGroup
,[ref]$strNetworkInterfacePropClusterAdapterID
,[ref]$oAPI
,[string]$strResourceGroupTypeFilter
,[ref]$discoverCSVResources
,[ref]$discoverNonCSVResources
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$oAPI.Value = New-object -ComObject "MOM.ScriptAPI"
if ([string]::IsNullOrEmpty($oAPI.Value) -or 0 -ne $error.Count)
{
$Message = $InitApiErrorMsg -f $error[0].Exception.Message
LogMessage $DBG_ERROR $message
exit -1
}

$result = Init-ScomHelper
if ($false -eq $result)
{
LogMessage $InitScomSerApiErrorMsg
exit -1
}

if([string]::IsNullOrEmpty($strNetworkInterfacePropClusterAdapterID.Value))
{
$strNetworkInterfacePropClusterAdapterID.Value = ""
}

if([string]::IsNullOrEmpty($strResourceGroupTypeFilter))
{
$strResourceGroupTypeFilter = $DefaultClusterGroupTypes
}

if([string]::IsNullOrEmpty($appendClusterNameToResourceGroup.Value))
{
$appendClusterNameToResourceGroup.Value = $false
}
else
{
$appendClusterNameToResourceGroup.Value = $true
}

$result = $strResourceGroupTypeFilter.Split(",")

$discoverCSVResources.Value = Convert-ToBoolean -sBool $discoverCSVResources
$discoverNonCSVResources.Value = Convert-ToBoolean -sBool $discoverNonCSVResources


return $result
}
#==========================================================================
# Initialize the arguments in Script
#==========================================================================


Function Log-StartParameters
{
$message = $StartParametersMsg -f ($SourceId,$ManagedEntityId,$HealthServiceName,$NetBiosName,$discoverUnusedNetworks,$networkContainsInterfaceGuid,$networkInterfaceTypeGuid,$networkInterfacePropClusterNameGuid,$networkInterfacePropNameGuid,$discoverCSVResources,$discoverNonCSVResources,$ResourceGroupDiscoveryLimit,$appendClusterNameToResourceGroup,$strNetworkInterfacePropClusterAdapterID,$strResourceGroupTypeFilter,$OsVersion)
LogMessage $DBG_TRACE $message

If ([string]::IsNullOrEmpty($SourceId) -or [string]::IsNullOrEmpty($ManagedEntityId) -or [string]::IsNullOrEmpty($HealthServiceName) -or [string]::IsNullOrEmpty($NetBiosName))
{
$message = $ErrorStartParametersMsg -f ($SourceId,$ManagedEntityId,$HealthServiceName,$NetBiosName)
LogMessage $DBG_ERROR $message
exit -1
}
}


#==========================================================================
# Main
#==========================================================================
$ErrorActionPreference = "SilentlyContinue"
Log-StartParameters

$GroupFilter = Initialize-DiscoveryScript -appendClusterNameToResourceGroup ([ref]$appendClusterNameToResourceGroup) -strNetworkInterfacePropClusterAdapterID ([ref]$strNetworkInterfacePropClusterAdapterID) -oAPI ([ref]$oAPI) -discoverCSVResources ([ref]$discoverCSVResources) -discoverNonCSVResources ([ref]$discoverNonCSVResources) -strResourceGroupTypeFilter $strResourceGroupTypeFilter
$discoveryData = DiscoverInstances -ComputerName $HealthServiceName -NetBiosName $NetBiosName -NetworkInterfaceTypeGuid $NetworkInterfaceTypeGuid -NetworkContainsInterfaceGuid $NetworkContainsInterfaceGuid -networkInterfacePropClusterNameGuid $networkInterfacePropClusterNameGuid -networkInterfacePropNameGuid $networkInterfacePropNameGuid -strNetworkInterfacePropClusterAdapterID $strNetworkInterfacePropClusterAdapterID -discoverUnusedNetworks $discoverUnusedNetworks -ResourceGroupDiscoveryLimit $ResourceGroupDiscoveryLimit -GroupFilter $GroupFilter -discoverNonCSVResources $discoverNonCSVResources -discoverCSVResources $discoverCSVResources -appendClusterNameToResourceGroup $appendClusterNameToResourceGroup -OSVersion $OsVersion

if ($null -ne $discoveryData)
{
$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($discoveryData)
Write-Host "$SerializeDiscoveryData"
}

Function Load-CimModules
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()

}
}</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>DiscoverClustering.vbs</Name>
<Contents><Script>'Copyright (c) Microsoft Corporation. All rights reserved.
Option Explicit

SetLocale("en-us")

Const DiscoveryScriptName = "DiscoverClustering.vbs Version 2.0."
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 wbemCimtypeUnknown = -1

Const Int32MaxValue = 2147483647
Const Int32MinValue = -2147483648

Const WMI_INVALID_NAMESPACE = -2147217391
Const WMI_INVALID_CLASS = -2147217392
Const WMI_INVALID_QUERY = -2147217385
Const WMI_INVALID_METHOD = -2147217362
Const WMI_INVALID_PROPERTY = 438

Const ErrAction_None = 0
Const ErrAction_Trace = 1
Const ErrAction_ThrowError = 16
Const ErrAction_Abort = 32
Const ErrAction_ThrowErrorAndAbort = 48
Const DefaultClusterGroupTypes = ""
Const DefaultResourceLimit = 300

Const Start_SnapShotDiscovery = 0
Const Exit_SnapShotDiscovery = 1
Const Exit_IncrementalDiscovery = 2


Const EventTypeError = 1
Const EventTypeWarning = 2
Const EventTypeInformation = 0
Const ScriptEventId = 7001

Const DefaultStringMaxSize = 256
Const ObjectNameStringMaxSize = 4000
Const GuidStringSize = 38
Const Win2016VersionPrefix = "10."
'===================================================
' Global Variables
'===================================================
Dim g_oUtil
Dim g_oClusterUtil
Dim ScriptParams

Call Main
'==========================================================================
' Main
'==========================================================================
Sub Main
Dim result
Dim IsArgs

result = StartInitialization(IsArgs)

If (False = result) Then
Exit Sub
End If

Call DiscoverInstances(IsArgs)

End Sub 'Main

Function GetIsGuidFlag(sOsVersion)

Dim IsGuid

IsGuid = False

On Error Resume Next

If (True = HasValue(sOsVersion)) Then
If (Len(sOsVersion) &gt;= 3) Then
If (Win2016VersionPrefix = Left(sOsVersion,3)) Then
IsGuid = True
End If
End If
End If

GetIsGuidFlag = IsGuid

End Function

Sub StartDiscovery(DiscoveryType,sOsVersion)

Dim IsGuid
Dim result
Dim message

On Error Resume Next
If (Exit_IncrementalDiscovery = DiscoveryType) Then
ScriptParams.oDiscoveryData.IsSnapshot = False
Else
If (Start_SnapShotDiscovery = DiscoveryType) Then
IsGuid = GetIsGuidFlag(sOsVersion)
result = ScriptParams.DiscoverWindowsCluster(IsGuid)
If (False = result) Then
Call ScriptParams.ThrowEmptyDiscoveryData(False)
message = "There is error during discovery cluster objects."
message = GetErrorMessage(message)
g_oUtil.LogMessage g_oUtil.DBG_ERROR, message
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
End If

End If
End If

End Sub

Sub DiscoverInstances(ByVal IsArgs)

On Error Resume Next

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

Dim message
Dim result
Dim DiscoveryType
Dim sOsVersion
Dim IsCluster

result = ScriptParams.InitDiscovery()

If (false = result) Then
Exit Sub
End If

If (False = IsArgs) Then
ScriptParams.oDiscoveryData.IsSnapshot = False
Call ScriptParams.PostDiscoveryData()
Exit Sub
End If

IsCluster = g_oCLusterUtil.CheckWinClusterPresent()

If (False = IsCluster) Then
Call ScriptParams.PostDiscoveryData()
Exit Sub
End If

sOsVersion = ScriptParams.OsVersion
DiscoveryType = g_oClusterUtil.GetSnapshotDiscovery(sOsVersion)

Call StartDiscovery(DiscoveryType,sOsVersion)
Call ScriptParams.PostDiscoveryData()

WScript.Echo ""
g_oUtil.LogMessage g_oUtil.DBG_TRACE, "Finished dicovery at machine local time: " &amp; CStr(Time)

On Error Goto 0
End Sub

'===================================================
' Global Initialization
'===================================================
Function StartInitialization(ByRef IsArgs)
On Error Resume Next
Dim message

StartInitialization = False
IsArgs = False

Set g_oUtil = New Util

If (0&lt;&gt;Err.number) Then

message = "Failed to initialize engine."
message = GetErrorMessage(message)
WScript.Echo message
Exit Function
End If

Set g_oClusterUtil = new ClusterUtil
If (0&lt;&gt;Err.number) Then
message = "Failed to initialize cluster helper engine."
message = GetErrorMessage(message)
WScript.Echo message
Exit Function
End If

Set ScriptParams = New ScriptParameters
If (0&lt;&gt;Err.number) Then
message = "Failed to initialize script helper engine."
message = GetErrorMessage(message)
WScript.Echo message
Exit Function
End If

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_NONE)
If (0&lt;&gt;Err.number) Then
message = "Failed to initialize debug level."
message = GetErrorMessage(message)
WScript.Echo message
Exit Function
End If

Dim result

result = ScriptParams.Initialize(IsArgs)
StartInitialization = result

On Error Goto 0
End Function

'==========================================================================
' 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 WMIExecQueryNoAbort(ByVal sNamespace, ByVal sQuery)

Dim oWMI, oQuery, nInstanceCount, message

Set WMIExecQueryNoAbort = Nothing

On Error Resume Next
Set oWMI = GetObject(sNamespace)

If ((False = HasValue(oWMI)) Or (0 &lt;&gt; Err.number)) Then
message = "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."
message = GetErrorMessage(message)
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

Set oQuery = oWMI.ExecQuery(sQuery)

If ((False = HasValue(oQuery)) Or (0 &lt;&gt; Err.number)) Then
message = "The Query '" &amp; sQuery &amp; "' returned an invalid result set. Please check to see if this is a valid WMI Query."
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
nInstanceCount = oQuery.Count
If (0 &lt;&gt; Err.number) Then
message = "The Query '" &amp; sQuery &amp; "' did not return any valid instances. Please check to see if this is a valid WMI Query."
'Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

Set WMIExecQueryNoAbort = oQuery


End Function

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

Dim oWMI, oInstance, nInstanceCount, message

Set WMIGetInstances = Nothing

On Error Resume Next
Set oWMI = GetObject(sNamespace)
If ((False = HasValue(oWMI)) Or (0 &lt;&gt; Err.number)) Then
message = "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."
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

Set oInstance = oWMI.InstancesOf(sInstance)

If ((False = HasValue(oInstance)) Or (0 &lt;&gt; Err.number)) Then
message = "The class name '" &amp; sInstance &amp; "' returned no instances. Please check to see if this is a valid WMI class name."
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
nInstanceCount = oInstance.Count
If (0 &lt;&gt; Err.number) Then
message = "The class name '" &amp; sInstance &amp; "' did not return any valid instances. Please check to see if this is a valid WMI class name."
'Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Else
Set WMIGetInstances = oInstance
End If

End Function

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

Dim oWMI, oInstance, nInstanceCount
Dim message

Set WMIGetInstance = Nothing

On Error Resume Next
Set oWMI = GetObject(sNamespace)
If ((False = HasValue(oWMI)) Or (0 &lt;&gt; Err.number)) Then
message = "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."
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Exit Function
End If

Set oInstance = oWMI.Get(sInstancePath)
If ((True = IsNull(oInstance)) Or (0 &lt;&gt; Err.number)) Then
message = "The class name '" &amp; sInstancePath &amp; "' returned no instances. Please check to see if this is a valid WMI class name."
'Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Else
Set WMIGetInstance = oInstance
End If

End Function

Public Function GetNodeToActiveGroup(ClusterNameSpace,ByRef IsError)

On Error Resume Next

IsError = False
Set GetNodeToActiveGroup = Nothing

Dim oNodeToGroupDict
Dim oActiveNodes
Dim Query
Dim oService
Dim Count
Dim oActiveNode
Dim oGroup, oNode

Query = "select * from MSCluster_NodeToActiveGroup"

Set oNodeToGroupDict = CreateObject("Scripting.Dictionary")

If (0 &lt;&gt; Err.number) Then
Set oNodeToGroupDict = Nothing
IsError = True
Exit Function
End If

Set oService = GetObject(ClusterNameSpace)
If (0 &lt;&gt; Err.number) Then

Set oNodeToGroupDict = Nothing
Set oService = Nothing
IsError = True
Exit Function
End If

Set oActiveNodes = oService.ExecQuery(Query)
If (0 &lt;&gt; Err.number) Then
Set oNodeToGroupDict = Nothing
Set oService = Nothing
Set oActiveNodes = Nothing
IsError = True
Exit Function
End If

Count = oActiveNodes.Count
If (0 &lt;&gt; Err.number) Then
Set oNodeToGroupDict = Nothing
Set oService = Nothing
Set oActiveNodes = Nothing
IsError = True
Exit Function
End If

For Each oActiveNode in oActiveNodes
Set oGroup = oService.Get(oActiveNode.PartComponent)
Set oNode = oService.Get(oActiveNode.GroupComponent)
If (0 &lt;&gt; Err.number) Then
IsError = True
Exit For
End If

If (False = oNodeToGroupDict.Exists(oGroup.Name)) Then
Call oNodeToGroupDict.Add(oGroup.Name,oNode.Name)
If (0 &lt;&gt; Err.number) Then
IsError = True
Exit For
End If
End If
Next


Set oActiveNode = Nothing
Set oNode = Nothing
Set oGroup = Nothing
Set oService = Nothing
Set oActiveNodes = Nothing

Set GetNodeToActiveGroup = oNodeToGroupDict
End Function

Public Function GetResourceGroupType(oGroup)

GetResourceGroupType = Null

If (False = HasValue(oGroup)) Then
Exit Function
End if

On Error Resume Next
Dim GroupType,oGroupType

GroupType = oGroup.GroupType

If (0 = Err.Number) Then
GetResourceGroupType = GroupType
Exit Function
End If

Call Err.Clear()

Set oGroupType = oGroup.ExecMethod_("GetGroupType")
If (0 &lt;&gt; Err.Number) Then
' 2003 doesn't have method and property
If (WMI_INVALID_METHOD = Err.number) Then
Call Err.Clear()
End If
Exit Function
End if

GroupType = oGroupType.ReturnValue
If (0 = Err.Number) Then
GetResourceGroupType = GroupType
Else
Call Err.Clear()
End if

End Function

Public Function WMIGetIntegerProperty(oWmi, sPropName, defaultValue,ByRef IsError)
Dim result
Dim Value
Dim nCIMType
Dim Int32Value
Dim IsArray

result = 0
IsError = False
WMIGetIntegerProperty = result

If Not IsValidObject(oWmi) Then
Exit Function
End If

On Error Resume Next
Value = GetWmiVRawValueFromProperty(oWmi, sPropName, nCIMType, IsError,IsArray)
If (True = IsError) Then
Exit Function
End If

If IsNull(Value) Then
Exit Function
End If

If (wbemCimtypeUnknown = nCIMType) Then
Int32Value = CLng(Value)

If (0 = Err.Number) Then
result = Int32Value
Else
result = defaultValue
IsError = True
End If
Else
result = GetIntegerFromWmiProp(Value,nCIMType,defaultValue,IsArray)
End If

WMIGetIntegerProperty = result
On Error Goto 0
End Function

Public Function WMIGetStringProperty(oWmi, sPropName,ByRef IsError)
Dim result
Dim Value
Dim nCIMType
Dim sValue
Dim IsArray

result = ""
IsError = False
WMIGetStringProperty = result

If Not IsValidObject(oWmi) Then
Exit Function
End If

On Error Resume Next
Value = GetWmiVRawValueFromProperty(oWmi, sPropName, nCIMType, IsError,IsArray)
If (True = IsError) Then
Exit Function
End If

If IsNull(Value) Then
Exit Function
End If

If (wbemCimtypeUnknown = nCIMType) Then
sValue = CStr(Value)

If (0 = Err.Number) Then
result = sValue
Else
IsError = True
End If
Else
result = GetStringFromWmiProp(Value,nCIMType,IsArray)
End If

WMIGetStringProperty = result
On Error Goto 0
End Function

Private Function GetWmiVRawValueFromProperty(oWmi, sPropName,ByRef nCIMType,ByRef IsError,ByRef IsArray)
On Error Resume Next
Dim Value
Dim oWmiProp

nCIMType = -1
IsError = False
GetWmiVRawValueFromProperty = ""

Set oWmiProp = oWmi.Properties_.Item(sPropName)
If Err.Number &lt;&gt; 0 Then
IsError = True
Call Err.Clear()
Exit Function
End If

If (False = IsValidObject(oWmiProp)) Then
IsError = True
Exit Function
End If

Value = oWmiProp.Value
If Err.Number &lt;&gt; 0 Then
IsError = True
Call Err.Clear()
End If

nCIMType = oWmiProp.CIMType
If Err.Number &lt;&gt; 0 Then
nCIMType = wbemCimtypeUnknown
IsError = True
Call Err.Clear()
End If

IsArray = oWmiProp.IsArray
If Err.Number &lt;&gt; 0 Then
IsArray = False
IsError = True
End If

GetWmiVRawValueFromProperty = Value
On Error Goto 0
End Function

Private Function GetLargeInteger(iValue,defaultValue)
On Error Resume Next
Dim result

result = iValue
If ( iValue &gt; Int32MaxValue) Then
result = defaultValue
ElseIf (iValue &lt; Int32MinValue) Then
result = defaultValue
End If

GetLargeInteger = result
On Error Goto 0
End Function

Private Function GetIntegerFromDouble(Value,defaultValue)
On Error Resume Next
Dim result

result = Value
If ( Value &gt; Int32MaxValue) Then
result = defaultValue
ElseIf (Value &lt; Int32MinValue) Then
result = defaultValue
Else
result = CLng(Value)
End If

GetIntegerFromDouble = result
On Error Goto 0
End Function

Private Function GetStringFromDateTime(Value)
On Error Resume Next
Dim result
Dim sTmpStrDate,sValue

result = ""
sValue = CStr(Value)

If Err.number &lt;&gt; 0 Then
Exit Function
End If
result = sValue

' 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
result = 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
result = sTmpStrDate
End If
End If

GetStringFromDateTime = result
On Error Goto 0
End Function

Private Function GetIntegerFromWmiProp(Value,nCIMType,defaultValue,IsArray)
On Error Resume Next
Dim result
result = 0
Select Case (nCIMType)
Case wbemCimtypeSint16, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16:
If (False = IsArray) Then
result = CLng(Value)
Else
result = CLng(Value(0))
End If
Case wbemCimtypeSint32,wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
If (False = IsArray) Then
result = GetLargeInteger(Value,defaultValue)
Else
result = GetLargeInteger(Value(0),defaultValue)
End If
Case wbemCimtypeReal32, wbemCimtypeReal64:
If (False = IsArray) Then
result = GetIntegerFromDouble(Value,defaultValue)
Else
result = GetIntegerFromDouble(Value(0),defaultValue)
End If
Case wbemCimtypeBoolean:
If (1= Value) Or (UCase(Value) = "TRUE") Then
result = 1
End If
End Select

GetIntegerFromWmiProp = result
On Error Goto 0
End Function

Private Function GetStringFromWmiProp(Value,nCIMType,IsArray)
On Error Resume Next
Dim result
result = ""
Select Case (nCIMType)
Case wbemCimtypeString,wbemCimtypeSint16, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16,wbemCimtypeSint32,wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64,wbemCimtypeReal32, wbemCimtypeReal64:
If (False = IsArray) Then
result = CStr(Value)
Else
result = Join(Value, ", ")
End If
Case wbemCimtypeDatetime:
result = GetStringFromDateTime(Value)
Case wbemCimtypeBoolean:
If (1= Value) Or (UCase(Value) = "TRUE") Then
result = "true"
Else
result = "false"
End If

End Select

GetStringFromWmiProp = result
On Error Goto 0
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 Function DiscoverClusterContainsRelationship( _
ByRef oSourceInstance, _
ByRef oTargetInstance, _
ByVal discoveryRelationshipClass, _
ByRef oDiscoveryData _
)

On Error Resume Next
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains objects."

Dim result

result = false
DiscoverClusterContainsRelationship = result
Call Err.Clear()

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance(discoveryRelationshipClass)

If ( (False = HasValue(oRelationshipInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oRelationshipInstance = Nothing
Exit Function
End If

oRelationshipInstance.Source = oSourceInstance
oRelationshipInstance.Target = oTargetInstance

If (0 &lt;&gt; Err.Number)Then
Set oRelationshipInstance = Nothing
Exit Function
End If

Call oDiscoveryData.AddInstance(oRelationshipInstance)
result = (0 = Err.number)

Set oRelationshipInstance = Nothing

DiscoverClusterContainsRelationship = result
End Function

Private Function GetOsFilter(OSVersion,delimiter)

On Error Resume Next
Err.Clear

Dim Filter,Prefix,Separator,EndClause
Dim OsVersions,SubFilter

Filter = " where ProductType != 1"
GetOSFilter = Filter

If (Not HasValue(OSVersion) or 0 = Len(OSVersion)) Then
Exit Function
End If
If (Not HasValue(delimiter)) Then
delimiter = ","
End If

If (delimiter = OSVersion) Then
Exit Function
End If

Prefix = " and (Version like '"
Separator = "%' or Version like '"
EndClause = "%')"

OsVersions = Split(OSVersion,delimiter)

SubFilter = Join(OsVersions,Separator)
Filter = Filter &amp; Prefix &amp; SubFilter &amp; EndClause

GetOSFilter = Filter

On Error Goto 0
End Function

Private Function GetServerOsVersionCheck(sComputerName,ByRef OsVersion,ByRef IsError)

On Error Resume Next

Err.Clear

Dim strQuery,oWmiSet, sWmiTarget, Count, Filter
Dim oObject,OsVer

IsError = False
GetServerOsVersionCheck = False

If ( IsObject(OsVersion)) Then
Exit Function
End If

sWmiTarget = "."

If ( Not IsObject(sComputerName)) Then
If (HasValue(sComputerName) and Len(sComputerName) &gt; 0 ) Then
sWmiTarget = "" &amp; sComputerName
End If
End If

sWmiTarget = "winmgmts:\\" &amp; sWmiTarget &amp; "\root\cimv2"
Filter = GetOsFilter(OsVersion,",")
StrQuery = "select Version from Win32_OperatingSystem" &amp; Filter
Set oWmiSet = WMIExecQueryNoAbort(sWmiTarget, strQuery)

If Err.Number &lt;&gt; 0 Then
IsError = True
Exit Function
End If

Count = oWmiSet.Count
If Err.Number &lt;&gt; 0 Then
IsError = True
Exit Function
End If

OsVer = ""
For Each oObject in oWmiSet
OsVer = oObject.Version
If (0 = Err.Number) Then
OsVersion = OsVer
End If

Exit For
Next

GetServerOsVersionCheck = ( Count &gt; 0)

On Error Goto 0
End Function

Public Function GetSnapshotDiscovery(ByRef OsVersion)

Dim bIsOsValid,bIsError,iResult

On Error Resume Next

If ( False = HasValue(OsVersion)) Then
iResult = Start_SnapShotDiscovery
GetSnapshotDiscovery = iResult
Exit Function
End If

If ( "" = OsVersion) Then
iResult = Start_SnapShotDiscovery
GetSnapshotDiscovery = iResult
Exit Function
End If

bIsOsValid = GetServerOsVersionCheck(".",OsVersion,bIsError)

If (bIsOsValid) Then
iResult = Start_SnapShotDiscovery
Else
If (bIsError) Then
iResult = Exit_IncrementalDiscovery
Else
iResult = Exit_SnapShotDiscovery
End IF

End If

GetSnapshotDiscovery = iResult
End Function

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

On Error Resume Next

strKeyValue = ""
GetRegistryKeyValue = strKeyValue
IsError = False

Set oReg = CreateObject("WScript.Shell")

If (Err.Number &lt;&gt; 0) Then
IsError = True
Exit Function
End If

strKeyValue = oReg.RegRead(keyPath &amp; key)
If Err.Number &lt;&gt; 0 Then
strKeyValue = ""
End If

GetRegistryKeyValue = strKeyValue

' resume error
On Error Goto 0

End Function

Public Function CheckWinClusterPresent()
Const ClusterNamePath = "HKLM\Cluster\"
Const ClusterNameValue = "ClusterName"

Dim IsCluster
Dim IsError
Dim result
On Error Resume Next

IsCluster = GetRegistryKeyValue(ClusterNamePath,ClusterNameValue,IsError)
result = (True = IsError) Or ( (False = IsError) and (Len(IsCluster) &gt; 0 ) )
CheckWinClusterPresent = result
On Error Goto 0

End Function

End Class 'ClusterUtil

'===================================================
' Simple Common Functions
'===================================================

Function GetErrorMessage(message)

If ( 0 &lt;&gt; Len(Err.Description)) Then
message = message &amp; " Error: Id: " &amp; Err.number &amp; " Description:" &amp; Err.Description
End If

GetErrorMessage = message
End Function

Function HasValue(Value)

Dim bNothing

bNothing = false

IF ( IsObject(Value) ) THEN
IF (Nothing is Value) THEN
bNothing = true
END IF
END IF

HasValue = Not ( IsEmpty(Value) or bNothing or IsNull(Value) )
End Function


Function GetDispObjectName(ObjectName,PostFix)
Dim pLen,oLen
Dim delta, delta1
Dim result

oLen = Len(ObjectName)
pLen = Len(PostFix)
delta1 = pLen - ObjectNameStringMaxSize
delta = delta1 + oLen

result = ObjectName &amp; PostFix

If ( delta &gt; 0) Then
If (delta1 &gt;= 0) Then
result = Left(result,ObjectNameStringMaxSize)
Else
result = Left(ObjectName,-delta1) &amp; PostFix
End If
End If

GetDispObjectName = result
End Function

'==========================================================================
' 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()
If (0 &lt;&gt; Number) Then
Call Err.Raise(Number, Source, Description)
End If
End Sub

Sub RaiseError(iNumber, sSource, sDescription)
If (0 &lt;&gt; iNumber) Then
Call Err.Raise(iNumber, sSource, sDescription)
End If
End Sub

End Class

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

'==========================================================================
'Class Properties
' Used to say to LogMessage when/how to print the message.
'==========================================================================

Public DBG_NONE
Public DBG_ERROR
Public DBG_WARNING
Public DBG_TRACE
Public momAPI

'Internal Debug Level
Private m_nDebugLevel
Private m_Error
'==========================================================================
'Class Methods
' Used to say to LogMessage when/how to print the message.
'==========================================================================

Public Function CheckObject(oObject,message)
On Error Resume Next
CheckObject = True
If (False = HasValue(oObject) ) Then
CheckObject = False
message = GetErrorMessage(message)
LogMessage DBG_ERROR, message
Call LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
Call Err.Clear()
End If
End Function
'**********************************************************************
Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
On Error Resume Next
LogMessage _
DBG_ERROR, _
sMessage &amp; vbCrLf &amp; oErr.Description

Call LogScomEvent (DiscoveryScriptName, ScriptEventId, EventTypeError, "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 Sub LogScomEvent(ScriptName,EventId,EventType,message)

If (False = HasValue(momAPI)) Then
Exit Sub
End If

Call m_Error.Save()

On Error Resume Next
Call momAPI.LogScriptEvent (ScriptName, EventId, EventType, message)
Call Err.Clear()
Call m_Error.Raise()

End Sub

Public Function GetStringProperty(sProperty,MaxSize)
GetStringProperty = ""

Dim Value
Dim MaxLength

If ( (False = HasValue(sProperty)) Or (True = IsObject(sProperty)) ) Then
Exit Function
End If

If ( (False = HasValue(MaxSize)) Or (True = IsObject(MaxSize)) ) Then
MaxLength = DefaultStringMaxSize
Else
MaxLength = MaxSize
End If

Call m_Error.Save()

On Error Resume Next
Value = CStr(sProperty)

If (0 &lt;&gt; Err.Number) Then
Value = ""
Call Err.Clear()
Else
If ( Len(Value) &gt; MaxLength) Then
Value = Left(Value, MaxLength)
End If
End If

GetStringProperty = Value
Call m_Error.Raise()

End Function

Public Sub RaiseError(message)
On Error Resume Next

Call m_Error.RaiseError(ScriptEventId,DiscoveryScriptName,message)

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


'======================================================================
' 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
Set m_Error = New Error
End Sub

End Class ' Util



Class ScriptParameters
Public SourceId
Public ManagedEntityId
Public HealthServiceName
Public NetBiosName
Public discoverUnusedNetworks
Public networkContainsInterfaceGuid
Public networkInterfaceTypeGuid
Public networkInterfacePropClusterNameGuid
Public networkInterfacePropNameGuid
Public discoverCSVResources
Public discoverNonCSVResources
Public ResourceGroupDiscoveryLimit
Public appendClusterNameToResourceGroup
Public strNetworkInterfacePropClusterAdapterID
Public OsVersion
Public ObjResourceGroupTypeFilter

Public oAPI
Public oDiscoveryData

Private strResourceGroupTypeFilter
Private oWShell

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
On Error Resume Next
Set oWShell = CreateObject("WScript.Shell")
If (0 &lt;&gt; Err.number) Then
Set oWShell = Nothing
End If

strNetworkInterfacePropClusterAdapterID = ""
strResourceGroupTypeFilter = DefaultClusterGroupTypes
OsVersion = ""

On Error Goto 0
End Sub

Public Function Initialize(ByRef IsArgs)
Dim oArgs
Dim message

On Error Resume Next

Initialize = False
IsArgs = False

Set oAPI = CreateObject("MOM.ScriptAPI")
If ((False = HasValue(oAPI )) Or (0 &lt;&gt; Err.number)) Then
message = " " &amp; DiscoveryScriptName &amp; " : Failed to get MOM API. MOM v3 must be installed to execute this script."
message = GetErrorMessage(message)
g_oUtil.LogMessage g_oUtil.DBG_ERROR, message
Call LogEventToWs(EventTypeError,message)
Exit Function
End If

If (True = HasValue(g_oUtil)) Then
Set g_oUtil.momAPI = oAPI
End If

Set oArgs = WScript.Arguments

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

If oArgs.Count &lt; 2 Then
message = "Wrong number of arguments: " &amp; oArgs.Count &amp; " instead of minimal 12."
g_oUtil.LogMessage g_oUtil.DBG_ERROR, message

If (True = HasValue(g_oUtil)) Then
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)
End If

Exit Function
End If

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)

If oArgs.Count &gt;= 12 Then
IsArgs = True
Else
If ((True = HasValue(SourceId)) And (True = HasValue(ManagedEntityId)) ) Then
Initialize = True
End If
Exit Function
End If

HealthServiceName = oArgs(2)
NetBiosName = oArgs(3)
discoverUnusedNetworks = ConvertToBoolean(oArgs(4))
networkContainsInterfaceGuid = oArgs(5)
networkInterfaceTypeGuid = oArgs(6)
networkInterfacePropClusterNameGuid = oArgs(7)
networkInterfacePropNameGuid = oArgs(8)
discoverCSVResources = ConvertToBoolean(oArgs(9))
discoverNonCSVResources = ConvertToBoolean(oArgs(10))
Err.Clear
ResourceGroupDiscoveryLimit = CInt(oArgs(11))
If (0 &lt;&gt; Err.number) Then
Call Err.Clear()
ResourceGroupDiscoveryLimit = DefaultResourceLimit
End If

If ( oArgs.Count &lt; 13) Then
appendClusterNameToResourceGroup = false
Else
appendClusterNameToResourceGroup = ConvertToBoolean(oArgs(12))
End If

If ( oArgs.Count &gt; 13 ) Then
strNetworkInterfacePropClusterAdapterID = oArgs(13)
End If

'Adding New Parameter for Resource Group Types Filter
If ( oArgs.Count &gt; 14) Then
strResourceGroupTypeFilter = oArgs(14)
End If

If ( oArgs.Count &gt; 15) Then
OsVersion = Replace(oArgs(15), Chr(34), "")
End If

Err.Clear
ObjResourceGroupTypeFilter = Split(strResourceGroupTypeFilter , ",")
If (0 &lt;&gt; Err.number) Then
Call Err.Clear()
ObjResourceGroupTypeFilter = DefaultClusterGroupTypes
End If

Initialize = CheckScriptParameters()
End Function

Public Function ConvertToBoolean(Value)
On Error Resume Next

ConvertToBoolean = False
If (False = HasValue(Value)) Then
Exit Function
End If

If ( (True = IsObject(Value)) Or (True = IsArray(Value)) ) Then
Exit Function
End If

Dim bResult

bResult = CBool(Value)
If (0 &lt;&gt; Err.number) Then
bResult = false
Call Err.Clear()
End If

ConvertToBoolean = bResult
On Error Goto 0
End Function

Public Function InitDiscovery
InitDiscovery = False
On Error Resume Next

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

If ( (False = HasValue(oDiscoveryData)) Or (0 &lt;&gt; Err.Number) ) Then
Set oDiscoveryData = Nothing

message = "Failed to get Discovery Data Object. MOM v3 must be installed to execute this script."
message = GetErrorMessage(message)

g_oUtil.LogMessage g_oUtil.DBG_ERROR, message
Call g_oUtil.LogScomEvent(DiscoveryScriptName,ScriptEventId,EventTypeError,message)

Else
InitDiscovery = True
End If

On Error Goto 0
End Function

'==========================================================================
' FUNCTIONS
'==========================================================================
Sub ThrowEmptyDiscoveryData(IsSnapShot)
On Error Resume Next

If (False = HasValue(oAPI)) Then
Exit Sub
End If

Set oDiscoveryData = Nothing
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
If ((False = HasValue(oDiscoveryData)) Or (0 &lt;&gt; Err.Number)) Then
Call Err.Clear()
Exit Sub
End If

oDiscoveryData.IsSnapshot = IsSnapShot

On Error Goto 0
End Sub

Public Sub PostDiscoveryData()
On Error Resume Next

If (False = HasValue(oAPI)) Then
Exit Sub
End If

oAPI.Return(oDiscoveryData)

Set oDiscoveryData = Nothing
Set oAPI = Nothing
On Error Goto 0

End Sub

Public Sub LogEventToWs(EventType,message)
On Error Resume Next

If (False = HasValue(oWShell)) Then
Set oWShell = CreateObject("WScript.Shell")

If (0 &lt;&gt; Err.number) Then
Set oWShell = Nothing
On Error Goto 0
Exit Sub
End If
End If

Call oWShell.LogEvent(EventType,message)

On Error Goto 0
End Sub

Public Function DiscoverWindowsCluster(ByVal IsGuid)
Dim oWinCluster
Dim message
Dim result

DiscoverWindowsCluster = False
On Error Resume Next
message = "Failed to create cluster discovery helper objects."
Set oWinCluster = New WinCluster

result = g_oUtil.CheckObject(oWinCluster,message)
If (False = result) Then
Exit Function
End If

result = oWinCluster.Discover (_
ScriptParams.oDiscoveryData _
,ScriptParams.HealthServiceName _
,ScriptParams.NetBiosName _
,ScriptParams.networkInterfaceTypeGuid _
,ScriptParams.networkContainsInterfaceGuid _
,ScriptParams.networkInterfacePropClusterNameGuid _
,ScriptParams.networkInterfacePropNameGuid _
,ScriptParams.strNetworkInterfacePropClusterAdapterID _
,ScriptParams.discoverUnusedNetworks _
,ScriptParams.appendClusterNameToResourceGroup _
,ScriptParams.ObjResourceGroupTypeFilter _
,ScriptParams.ResourceGroupDiscoveryLimit _
,ScriptParams.discoverNonCSVResources _
,ScriptParams.discoverCSVResources _
,IsGuid _
)

Set oWinCLuster = Nothing
DiscoverWindowsCluster = result

End Function

Private Function CheckScriptParameters()

CheckScriptParameters = False
On Error Resume Next

If ((False = HasValue(SourceId)) Or (False = HasValue(ManagedEntityId)) Or (False = HasValue(HealthServiceName)) Or (False = HasValue(NetBiosName)) ) Then
Exit Function
End If

If ((False = HasValue(networkContainsInterfaceGuid)) Or (False = HasValue(networkInterfaceTypeGuid)) Or (False = HasValue(networkInterfacePropClusterNameGuid)) Or (False = HasValue(networkInterfacePropClusterNameGuid)) ) Then
Exit Function
End If

If ( ( GuidStringSize &gt; Len(Trim(SourceId))) Or (GuidStringSize &gt; Len(Trim(ManagedEntityId))) ) Then
Exit Function
End If

If ( (GuidStringSize &gt; Len(Trim(networkInterfaceTypeGuid))) Or (GuidStringSize &gt; Len(Trim(networkInterfacePropClusterNameGuid))) Or (GuidStringSize &gt; Len(Trim(networkInterfacePropClusterNameGuid))) ) Then
Exit Function
End If

If ( (0 = Len(Trim(HealthServiceName))) Or (0 = Len(Trim(NetBiosName))) Or (False = Len(Trim(networkContainsInterfaceGuid))) ) Then
Exit Function
End If

CheckScriptParameters = True

On Error Goto 0
End Function

End Class

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

Private ClusterNameSpace
Private GroupEventId
Private NodeEventId
Private NetEventId
Private ActiveNodesDict

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
ClusterNameSpace = "winmgmts:{impersonationLevel=impersonate}!\\.\root\mscluster"
GroupEventId = 7010
NodeEventId = 7030
NetEventId = 7020

End Sub


'==========================================================================
' Discover cluster classes
'==========================================================================
Function Discover( _
ByRef oDiscoveryData _
,ByVal ComputerName _
,ByVal NetBiosName _
,ByVal NetworkInterfaceTypeGuid _
,ByVal NetworkContainsInterfaceGuid _
,ByVal networkInterfacePropClusterNameGuid _
,ByVal networkInterfacePropNameGuid _
,ByVal strNetworkInterfacePropClusterAdapterID _
,ByVal discoverUnusedNetworks _
,ByVal appendClusterNameToResourceGroupName _
,ByVal GroupTypeFilter _
,ByVal ResourceGroupDiscoveryLimit _
,ByVal discoverNonCSVResources _
,ByVal discoverCSVResources _
,ByVal IsGuid _
)

Dim oCluster
Dim oClusterInstance
Dim oClusters

Dim result

result = false
Discover = result
On Error Resume Next

Set oClusters = g_oClusterUtil.WMIGetInstances(ClusterNameSpace, "MSCluster_Cluster")
If (0 &lt;&gt; Err.number) Then
Set oClusters = Nothing

If ((WMI_INVALID_NAMESPACE = Err.number) Or (WMI_INVALID_CLASS = Err.number)) Then
Discover = True
End If

Exit Function
End If

result = true

For Each oCluster in oClusters

Dim ClusterName

ClusterName = oCluster.Name
If (0 &lt;&gt; Err.number) Then
result = false
Exit For
End If


result = DiscoverClusterInstance(ClusterName, oClusterInstance,oDiscoveryData)
If (False = result) Then
Exit For
End If

result = DiscoverNodes(oCluster,ClusterName,oClusterInstance,oDiscoveryData,ComputerName,NetBiosName)
If (False = result) Then
Exit For
End If

result = DiscoverNetworks(oCluster,ClusterName,oClusterInstance,oDiscoveryData,ComputerName,NetBiosName,NetworkInterfaceTypeGuid,NetworkContainsInterfaceGuid,discoverUnusedNetworks,false,networkInterfacePropClusterNameGuid,networkInterfacePropNameGuid,strNetworkInterfacePropClusterAdapterID,IsGuid)
If (False = result) Then
Exit For
End If


result = DiscoverGroups(oCluster,NetBiosName,ClusterName,oClusterInstance,oDiscoveryData,ComputerName,GroupTypeFilter,appendClusterNameToResourceGroupName,ResourceGroupDiscoveryLimit,discoverNonCSVResources,discoverCSVResources)
If (False = result) Then
Exit For
End If

Next

Set oClusterInstance = Nothing
Set oCluster = Nothing
Set oClusters = Nothing

Discover = result
End Function

Private Function DiscoverClusterInstance(ByVal ClusterName, ByRef oClusterInstance, ByRef oDiscoveryData)
On Error Resume Next

Dim result

result = false
DiscoverClusterInstance = result
Set oClusterInstance = Nothing

Set oClusterInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Cluster!Microsoft.Windows.Cluster']$")
If ((False = HasValue(oClusterInstance)) Or (0 &lt;&gt; Err.number)) Then
Set oClusterInstance = Nothing
Exit Function
End If

Call oClusterInstance.AddProperty("$MPElement[Name='Cluster!Microsoft.Windows.Cluster']/Name$",ClusterName)
If (0 &lt;&gt; Err.number) Then
Set oClusterInstance = Nothing
Exit Function
End If

oDiscoveryData.AddInstance(oClusterInstance)
result = (0 = Err.number)

DiscoverClusterInstance = result
End Function

Private Function DiscoverNodes(oCluster,ClusterName,oClusterInstance,ByRef oDiscoveryData,ComputerName,NetBiosName)
' cluster node helpers

Dim oWinClusterNode
Dim oNodes
Dim result
Dim Count
Dim IsFound 'Flag for correct Node

result = False
DiscoverNodes = result

If (False = HasValue(oCluster)) Then
Exit Function
End If

On Error Resume Next

Set oWinClusterNode = new WinClusterNode
If ( (False = HasValue(oWinClusterNode)) Or (0 &lt;&gt; Err.Number) ) Then
Set oWinClusterNode = Nothing
Exit Function
End If

Set oNodes = oCluster.Associators_("MSCluster_ClusterToNode", "", "", "", False, False, "", "", 0)
If ( 0 &lt;&gt; Err.Number ) Then
Set oWinClusterNode = Nothing
Set oNodes = Nothing
Exit Function
End If

Count = oNodes.Count
If (0 &lt;&gt; Err.Number) Then
Set oWinClusterNode = Nothing
Set oNodes = Nothing
Exit Function
End If

If (0 = Count) Then
Set oWinClusterNode = Nothing
Set oNodes = Nothing
DiscoverNodes = True
Exit Function
End If

Dim oNode
result = true
IsFound = False

For Each oNode in oNodes

result = oWinClusterNode.DiscoverInstance (ClusterName, oNode,oDiscoveryData,ComputerName,NetBiosName,IsFound)
If (False = result) Then
Exit For
End If

If (True = IsFound) Then
result = oWinClusterNode.DiscoverClusterContainsRelationship(oClusterInstance, oDiscoveryData,ComputerName)
If (False = result) Then
Exit For
End If
End If
Next

Set oWinClusterNode = Nothing
Set oNode = Nothing
Set oNodes = Nothing

DiscoverNodes = result
End Function

Private Function DiscoverNetworks(oCluster,ClusterName,oClusterInstance,ByRef oDiscoveryData,ComputerName,NetBiosName,NetworkInterfaceTypeGuid,NetworkContainsInterfaceGuid,discoverUnusedNetworks,appendClusterNameToResourceGroupName,networkInterfacePropClusterNameGuid,networkInterfacePropNameGuid,strNetworkInterfacePropClusterAdapterID,IsGuid)

Dim oNetworks
Dim result
Dim Count

result = False
DiscoverNetworks = result

If (False = HasValue(oCluster)) Then
Exit Function
End If

On Error Resume Next

Set oNetworks = oCluster.Associators_("MSCluster_ClusterToNetwork", "", "", "", False, False, "", "", 0)
If (0 &lt;&gt; Err.Number) Then
Set oNetworks = Nothing
Exit Function
End If

Count = oNetworks.Count
If (0 &lt;&gt; Err.Number) Then
Set oNetworks = Nothing
Exit Function
End If

If (0 = Count) Then
DiscoverNetworks = True
Set oNetworks = Nothing
Exit Function
End If

Dim oNetwork
Dim oWinClusterNetwork
Set oWinClusterNetwork = new WinClusterNetwork

If ( (False = HasValue(oWinClusterNetwork)) Or (0 &lt;&gt; Err.Number) ) Then
Set oNetworks = Nothing
Set oWinClusterNetwork = Nothing
Exit Function
End If

result = true
For Each oNetwork in oNetworks
' cluster network helpers

Dim discoverNetworkEnabled
result = oWinClusterNetwork.DiscoverInstance ( _
ClusterName _
,oNetwork _
,oDiscoveryData _
,ComputerName _
,ClusterNameSpace _
,NetBiosName _
,NetworkInterfaceTypeGuid _
,NetworkContainsInterfaceGuid _
,discoverUnusedNetworks _
,appendClusterNameToResourceGroupName _
,networkInterfacePropClusterNameGuid _
,networkInterfacePropNameGuid _
,strNetworkInterfacePropClusterAdapterID _
,discoverNetworkEnabled _
,IsGuid _
)
If (False = result) Then
Exit For
End If

If (True = discoverNetworkEnabled) Then
result = oWinClusterNetwork.DiscoverClusterContainsRelationship(oClusterInstance,ClusterName,oNetwork.Name,oDiscoveryData)

If (False = result) Then
Exit For
End If

End If

Next

Set oWinClusterNetwork = Nothing
Set oNetwork = Nothing
Set oNetworks = Nothing

DiscoverNetworks = result

End Function

'******************************************************************************
' FUNCTION: IndexOf
' DESCRIPTION: Returns Index of Search Element Value Inside an Array
' RETURNS: Index Number if not found return -1
'******************************************************************************
Private 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

Private Function GetDiscoveryGroupFlag(GroupType,GroupTypeFilter)
GetDiscoveryGroupFlag = True

If (True = IsNull(GroupType)) Then
Exit Function
End If

If IndexOf(GroupTypeFilter,GroupType) &lt;&gt; -1 Then
GetDiscoveryGroupFlag = False
End If
End Function

Private Function DiscoverGroup( _
oWinClusterGroup _
,ComputerName _
,NetBiosName _
,ClusterName _
,oClusterInstance _
,oRealGroup _
,ByRef oDiscoveryData _
,GroupType _
,appendClusterNameToResourceGroupName _
,ActiveNodesDict _
,discoverNonCSVResources _
,discoverCSVResources _
)
Dim autoFailbackType
Dim description
Dim failbackWindowEnd
Dim failbackWindowStart
Dim failoverPeriod
Dim failoverThreshold
Dim persistentState
Dim result
Dim IsError
Dim defaultValue
Dim RealGroupName

defaultValue = -1
result = false
DiscoverGroup = result

RealGroupName = g_oClusterUtil.WMIGetStringProperty ( oRealGroup, "Name" , IsError)

If ((0 = Len(RealGroupName)) Or (True = IsError)) Then
Exit Function
End If
description = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oRealGroup, "Description" , IsError),DefaultStringMaxSize)
persistentState = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oRealGroup, "PersistentState" , IsError),DefaultStringMaxSize)
failbackWindowEnd = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oRealGroup, "FailbackWindowEnd" , IsError),DefaultStringMaxSize)
failbackWindowStart = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oRealGroup, "FailbackWindowStart", IsError),DefaultStringMaxSize)

autoFailbackType = g_oClusterUtil.WMIGetIntegerProperty ( oRealGroup, "AutoFailbackType" ,defaultValue, IsError)
failoverPeriod = g_oClusterUtil.WMIGetIntegerProperty ( oRealGroup, "FailoverPeriod" ,defaultValue, IsError )
failoverThreshold = g_oClusterUtil.WMIGetIntegerProperty ( oRealGroup, "FailoverThreshold",defaultValue, IsError )

On Error Resume Next

result = oWinClusterGroup.DiscoverInstance ( _
ClusterName _
,oRealGroup _
,RealGroupName _
,autoFailbackType _
,description _
,failbackWindowEnd _
,failbackWindowStart _
,failoverPeriod _
,failoverThreshold _
,persistentState _
,oDiscoveryData _
,GroupType _
,appendClusterNameToResourceGroupName _
,ActiveNodesDict _
,NetBiosName _
) _

If (False = result) Then
Exit Function
End if

result = oWinClusterGroup.DiscoverClusterContainsRelationship( _
oClusterInstance _
,ClusterName _
,RealGroupName _
,oDiscoveryData _
) _

If (False = result) Then
Exit Function
End if

result = oWinClusterGroup.DiscoverInstanceForHosted ( _
ClusterName _
,oRealGroup _
,RealGroupName _
,autoFailbackType _
,description _
,failbackWindowEnd _
,failbackWindowStart _
,failoverPeriod _
,failoverThreshold _
,persistentState _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
) _

If (False = result) Then
Exit Function
End if

' group contains hosted group
result = oWinClusterGroup.DiscoverClusterGroupContainsRelationship( _
ClusterName _
,RealGroupName _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
)

If (False = result) Then
Exit Function
End if

If ( (True = discoverNonCSVResources) Or (True = discoverCSVResources) ) Then
result = oWinClusterGroup.DiscoverAllResources( _
ClusterName _
,RealGroupName _
,oRealGroup _
,GroupType _
,discoverNonCSVResources _
,discoverCSVResources _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
,ClusterNameSpace _
)
End If

DiscoverGroup = result
End Function

Private Function InitDiscoveryGroups(ByVal oCluster,ByRef oWinClusterGroup,ByRef oGroups, ByRef Count)

InitDiscoveryGroups = false

If (False = HasValue(oCluster)) Then
Exit Function
End If

On Error Resume Next
Set oWinClusterGroup = new WinClusterGroup

If ( (False = HasValue(oWinClusterGroup)) Or (0 &lt;&gt; Err.Number) ) Then
Set oWinClusterGroup = Nothing
Exit Function
End If

' groups
Dim IsError

Set oGroups = oCluster.Associators_("MSCluster_ClusterToResourceGroup", "", "", "", False, False, "", "", 0)

If ( 0 &lt;&gt; Err.Number ) Then
Set oWinClusterGroup = Nothing
Set oGroups = Nothing
Exit Function
End If

Count = oGroups.Count

If ( 0 &lt;&gt; Err.Number ) Then
Set oWinClusterGroup = Nothing
Set oGroups = Nothing
Exit Function
End If

If ( 0 = Count ) Then
Set oWinClusterGroup = Nothing
Set oGroups = Nothing
InitiDiscoveryGroups = True
Exit Function
End If

Set ActiveNodesDict = g_oClusterUtil.GetNodeToActiveGroup(ClusterNameSpace, IsError)

If ((True = IsError) Or (False = HasValue(ActiveNodesDict)) ) Then
Set winClusterGroup = Nothing
Set oGroups = Nothing
Set ActiveNodesDict = Nothing
Exit Function
End If

InitDiscoveryGroups = True

End Function

Private Function DiscoverGroups(oCluster,NetBiosName,ClusterName,oClusterInstance,ByRef oDiscoveryData,ComputerName,GroupTypeFilter,appendClusterNameToResourceGroupName,ResourceGroupDiscoveryLimit,discoverNonCSVResources,discoverCSVResources)

Dim oWinClusterGroup,oGroups,Count
Dim result

result = InitDiscoveryGroups(oCluster,oWinClusterGroup,oGroups, Count)
DiscoverGroups = result

If (False = result) Then
Exit Function
End If

On Error Resume Next


If ( 0 = Count ) Then
DiscoverGroups = True
Exit Function
End If

Dim oGroup
Dim iGroupCounter
Dim boolDiscoverGroup
Dim GroupType
Dim message

iGroupCounter = 0
result = true

For Each oGroup in oGroups

GroupType = g_oClusterUtil.GetResourceGroupType(oGroup)
boolDiscoverGroup = GetDiscoveryGroupFlag(GroupType,GroupTypeFilter)

If (True = boolDiscoverGroup) 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
message = "" &amp; ComputerName &amp; " hosts " &amp; iGroupCounter &amp; " cluster resource groups which exceeds the configured threshold of " &amp; ResourceGroupDiscoveryLimit &amp; "."
Call g_oUtil.LogScomEvent(DiscoveryScriptName,GroupEventId,EventTypeWarning,message)
Exit For
Else
' no
' proceed with normal discovery
result = DiscoverGroup( _
oWinClusterGroup _
,ComputerName _
,NetBiosName _
,ClusterName _
,oClusterInstance _
,oGroup _
,oDiscoveryData _
,GroupType _
,appendClusterNameToResourceGroupName _
,ActiveNodesDict _
,discoverNonCSVResources _
,discoverCSVResources _
)

If (False = result) Then
Exit For
End If

End If

End if

Next

Set oGroup = Nothing
Set oWinClusterGroup = Nothing
Set oGroups = Nothing
Set ActiveNodesDict = Nothing

DiscoverGroups = result
End Function
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 _
,ByVal ComputerName _
,ByVal NetBiosName _
,ByRef IsFound _
)

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

Dim NodeName
Dim description
Dim buildNumber
Dim cSDVersion
Dim majorVersion
Dim minorVersion
Dim nodeHighestVersion
Dim nodeLowestVersion
Dim IsError
Dim defaultValue
Dim result
Dim oInstance

result = false
DiscoverInstance = result

IsFound = False

If (False = HasValue(oObject) ) Then
Exit Function
End If

NodeName = Trim(g_oClusterUtil.WMIGetStringProperty ( oObject, "Name", IsError))

If (( 0 = Len(NodeName)) Or (True = IsError)) Then
Exit Function
End If

If (StrComp ( LCase(NetBiosName) , LCase(NodeName) ) &lt;&gt; 0 ) Then
DiscoverInstance = True
Exit Function
End If

description = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "Description", IsError),DefaultStringMaxSize)
buildNumber = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "BuildNumber" , defaultValue, IsError)
cSDVersion = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "CSDVersion" , defaultValue, IsError )
majorVersion = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "MajorVersion" , defaultValue, IsError )
minorVersion = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "MinorVersion" , defaultValue, IsError )
nodeHighestVersion = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "NodeHighestVersion", defaultValue, IsError )
nodeLowestVersion = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "NodeLowestVersion" , defaultValue, IsError )

NodeName = g_oUtil.GetStringProperty(NodeName,DefaultStringMaxSize)

On Error Resume Next

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

Call Err.Clear()
Set oInstance = oDiscoveryData.CreateClassInstance( "$MPElement[Name='Microsoft.Windows.Cluster.Node']$")
If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Exit Function
End If

With oInstance

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

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

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

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


.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
End With

If (0 &lt;&gt; Err.Number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance(oInstance)
If (0 &lt;&gt; Err.Number) Then
Exit Function
End If

IsFound = True

result = DiscoverClusterNodeRole ( hostKey, NodeName, oDiscoveryData, ComputerName)

DiscoverInstance = result

On Error Goto 0
End Function

'==========================================================================
' Discover node hostinging role relationship instance
'==========================================================================
Private Function DiscoverClusterNodeRole( _
ByVal hostKey _
,ByVal NodeName _
,ByRef oDiscoveryData _
,ByVal ComputerName _
)

Dim result
Dim oNodeRoleInstance

result = false
DiscoverClusterNodeRole = result

On Error Resume Next

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

Call Err.Clear()


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

If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(oNodeRoleInstance)) ) Then
Exit Function
End If

Call oNodeRoleInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", ComputerName)
Call oNodeRoleInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", NodeName)

If (0 &lt;&gt; Err.Number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance( oNodeRoleInstance)
result = (0 = Err.Number)

DiscoverClusterNodeRole = result
On Error Goto 0
End Function

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

Dim oInstance
Dim result

result = false
DiscoverClusterContainsRelationship = result

If (False = HasValue(oClusterInstance) ) Then
Exit Function
End If

On Error Resume Next
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains nodes."

Call Err.Clear()

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

If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Exit Function
End If

Call oInstance.AddProperty ("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", ComputerName)

If (0 &lt;&gt; Err.Number) Then
Exit Function
End If

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

DiscoverClusterContainsRelationship = result

On Error Goto 0
End Function

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 _
,ByVal ComputerName _
,ByVal ClusterNameSpace _
,ByVal NetBiosName _
,ByVal NetworkInterfaceTypeGuid _
,ByVal NetworkContainsInterfaceGuid _
,ByVal discoverUnusedNetworks _
,ByVal appendClusterNameToResourceGroupName _
,ByVal networkInterfacePropClusterNameGuid _
,ByVal networkInterfacePropNameGuid _
,ByVal strNetworkInterfacePropClusterAdapterID _
,ByRef discoverNetworkEnabled _
,ByVal IsGuid _
)

Dim clusterHelper
Dim result
Dim IsError
Dim oInstance
Dim ObjectName
Dim address
Dim addressMask
Dim role
Dim description
Dim defaultValue

result = False
DiscoverInstance = result

If (False = HasValue(oObject) ) Then
Exit Function
End If

role = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "Role", defaultValue, IsError )
If (True = IsError) Then
Exit Function
End If

roleNone = (0 = role)

If ( (False = discoverUnusedNetworks) and (True = roleNone) ) Then
discoverNetworkEnabled = False
DiscoverInstance = True
Exit Function
Else
discoverNetworkEnabled = True
End If

On Error Resume Next

Set clusterHelper = new WinClusterObject
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(clusterHelper)) ) Then
Set ClusterHelper = Nothing
Exit Function
End If

ObjectName = g_oClusterUtil.WMIGetStringProperty ( oObject, "Name" , IsError)

If ((0 = Len(ObjectName)) Or (True = IsError)) Then
Exit Function
End If

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

If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(oInstance)) ) Then
Set oInstance = Nothing
Exit Function
End If


defaultValue = -1
address = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "Address" , IsError) , DefaultStringMaxSize)
addressMask = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "AddressMask", IsError) , DefaultStringMaxSize)
description = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "Description", IsError) , DefaultStringMaxSize)

With oInstance


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

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


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


End With

If (0 &lt;&gt; Err.Number) Then
Set oInstance = Nothing
Exit Function
End If


Call oDiscoveryData.AddInstance(oInstance)
If (0 &lt;&gt; Err.Number) Then
Set oInstance = Nothing
Exit Function
End If


result = DiscoverNetItfs( _
hostkey _
,ObjectName _
,oObject _
,oDiscoveryData _
,ComputerName _
,ClusterNameSpace _
,NetBiosName _
,NetworkInterfaceTypeGuid _
,NetworkContainsInterfaceGuid _
,discoverUnusedNetworks _
,networkInterfacePropClusterNameGuid _
,networkInterfacePropNameGuid _
,strNetworkInterfacePropClusterAdapterID _
,IsGuid _
)

Set oInstance = Nothing

DiscoverInstance = result
End Function

Private Function DiscoverNetItfs(_
ByVal hostKey _
,ByVal NetName _
,ByVal oObject _
,ByRef oDiscoveryData _
,ByVal ComputerName _
,ByVal ClusterNameSpace _
,ByVal NetBiosName _
,ByVal NetworkInterfaceTypeGuid _
,ByVal NetworkContainsInterfaceGuid _
,ByVal discoverUnusedNetworks _
,ByVal networkInterfacePropClusterNameGuid _
,ByVal networkInterfacePropNameGuid _
,ByVal strNetworkInterfacePropClusterAdapterID _
,ByVal IsGuid _
)

On Error Resume Next

Dim result
Dim oNetworkItfs
Dim oNetworkItf
Dim oWinClusterNetworkInterface
Dim baseOSItfName
Dim NetIfSysName
Dim Count
Dim IsFound
Dim AdapterId

result = false
DiscoverNetItfs = result

If (False = HasValue(oObject) ) Then
Exit Function
End If

Set oNetworkItfs = oObject.Associators_("MSCluster_NetworkToNetworkInterface", "", "", "", False, False, "", "", 0)
If (0 &lt;&gt; Err.Number) Then
Set oNetworkItfs = Nothing
Exit Function
End If

Count = oNetworkItfs.Count
If (0 &lt;&gt; Err.Number) Then
Set oNetworkItfs = Nothing
Exit Function
End If

If (0 = Count) Then
DiscoverNetItfs = True
Set oNetworkItfs = Nothing
Exit Function
End If

Set oWinClusterNetworkInterface = new WinClusterNetworkInterface
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(oWinClusterNetworkInterface)) ) Then
Set oWinClusterNetworkInterface = Nothing
Set oNetworkItfs = Nothing
Exit Function
End If

result = true
IsFound = False
For Each oNetworkItf in oNetworkItfs
AdapterId = ""
baseOSItfName = GetNetIfName(oNetworkItf,NetIfSysName,AdapterId)
g_oUtil.LogMessage g_oUtil.DBG_TRACE, "Network: " &amp; NetName &amp; " interface: " &amp; baseOSItfName

If (0 &lt;&gt; Len(Trim(baseOSItfName)) and (LCase(NetIfSysName) = LCase(NetBiosName)) ) Then
result = oWinClusterNetworkInterface.Initialize ( baseOSItfName,AdapterId, discoverUnusedNetworks, IsGuid )
If (False = result) Then
Exit For
End If

result = oWinClusterNetworkInterface.DiscoverInstance ( _
hostKey _
,baseOSItfName _
,oNetworkItf _
,oDiscoveryData _
,ComputerName _
,NetworkInterfaceTypeGuid _
,networkInterfacePropClusterNameGuid _
,networkInterfacePropNameGuid _
,strNetworkInterfacePropClusterAdapterID _
,IsFound _
)
If (False = result) Then
Exit For
End If

If (True = IsFound) Then
' discover that network contains interfaces
result = DiscoverContainsNetworkInterfacesRelationship ( _
hostKey _
,NetName _
,oWinClusterNetworkInterface.deviceID _
,NetIfSysName _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
,NetworkInterfaceTypeGuid _
,NetworkContainsInterfaceGuid _
)
If (False = result) Then
Exit For
End If
End If
End If
Next


Set oNetworkItf = Nothing
Set oNetworkItfs = Nothing

DiscoverNetItfs = result
End Function


'==========================================================================
' Discover cluster containing network interfaces relationship instance
'==========================================================================
Private Function DiscoverContainsNetworkInterfacesRelationship( _
ByVal hostKey _
,ByVal networkKey _
,ByVal networkItfKey _
,ByRef NetIfSysName _
,ByRef oDiscoveryData _
,Byval ComputerName _
,ByVal NetBiosName _
,ByVal NetworkInterfaceTypeGuid _
,ByVal NetworkContainsInterfaceGuid _
)

Dim SysName, IsError
Dim result
Dim TrimKey

result = false
DiscoverContainsNetworkInterfacesRelationship = result

On Error Resume Next
If ( 0 &lt;&gt; StrComp (LCase(NetBiosName) , LCase(NetIfSysName)) ) Then
DiscoverContainsNetworkInterfacesRelationship = True
Exit Function
End If

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

Call Err.Clear()
Dim oNetworkInstance
Set oNetworkInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Network']$")
If ( (False = HasValue(oNetworkInstance)) Or (0 &lt;&gt; Err.number)) Then
Set oNetworkInstance = Nothing
Exit Function
End If

TrimKey = Trim(networkKey)
networkKey = g_oUtil.GetStringProperty(TrimKey,ObjectNameStringMaxSize)
With oNetworkInstance

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

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

End With

If (0 &lt;&gt; Err.number) Then
Set oNetworkInstance = Nothing
Exit Function
End If

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance(NetworkInterfaceTypeGuid)
If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.number)) Then
Set oInstance = Nothing
Exit Function
End If

With oInstance

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

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

End With

If (0 &lt;&gt; Err.number) Then
Set oInstance = Nothing
Exit Function
End If

Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance(NetworkContainsInterfaceGuid)
If ( (False = HasValue(oRelationshipInstance)) Or (0 &lt;&gt; Err.number)) Then
Exit Function
End If

oRelationshipInstance.Source = oNetworkInstance
oRelationshipInstance.Target = oInstance

Call oDiscoveryData.AddInstance(oRelationshipInstance)
result = (0 = Err.number)
Set oRelationshipInstance = Nothing
Set oInstance = Nothing
Set oNetworkInstance = Nothing

DiscoverContainsNetworkInterfacesRelationship = result
End Function

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

Dim result
Dim TrimKey

result = false
DiscoverClusterContainsRelationship = result

If (True = roleNone) Then
DiscoverClusterContainsRelationship = True
Exit Function
End If

On Error Resume Next

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

Dim oInstance
Call Err.Clear()
Set oInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Network']$")
If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.number)) Then
Set oInstance = Nothing
Exit Function
End If

TrimKey = Trim(networkKey)
networkKey = g_oUtil.GetStringProperty(TrimKey,ObjectNameStringMaxSize)

With oInstance

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

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

End With

If (0 &lt;&gt; Err.number) Then
Set oInstance = Nothing
Exit Function
End If

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

Set oInstance = Nothing
DiscoverClusterContainsRelationship = result
End Function

'============================================================
'Get Network Name from DeviceId
'OS &lt; 2008
'DeviceId=NetName - SystemName
'OS &gt;= 2008
' DeviceId=SystemName - NetName
'===========================================================
Private Function GetNetIfName(oNetworkItf,ByRef NetIfSysName,ByRef AdapterId)
On Error Resume Next
Dim systemName
Dim deviceId
Dim result
Dim lp,rp
Dim sysLen,dLen,delta
Dim IsError
Dim NicId

result = ""
GetNetIfName = result

systemName = g_oClusterUtil.WMIGetStringProperty ( oNetworkItf, "SystemName" , IsError)
deviceId = g_oClusterUtil.WMIGetStringProperty ( oNetworkItf, "DeviceID" , IsError)
NicId = g_oClusterUtil.WMIGetStringProperty ( oNetworkItf, "AdapterId" , IsError)
sysLen = Len(systemName)
dLen = Len(deviceId)
NetIfSysName = systemName
AdapterId = NicId

If ( (0 = sysLen) Or (3 &gt;= dLen) Or (dLen &lt;= sysLen ) ) Then
Exit Function
End If

systemName = LCase(SystemName)
delta = dLen - sysLen

If (delta &lt;= 3) Then
Exit Function
Else
delta = delta -3
End If

lp = Left(deviceId, sysLen)
rp = Right(deviceId, sysLen)

If (systemName = LCase(lp)) Then
result = Right(deviceId, delta)
Else
If (systemName = LCase(rp)) Then
result = Left(deviceId, delta)
End If
End If

GetNetIfName = result
On Error Goto 0
End Function
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
Public description

Private NameSpace
Private DHCPEnabled
Private IPAddress
Private IPSubnet
Private DNSDomain
Private DHCPServer
Private IpEnabled
Private DefaultIPGateway




'======================================================================
' Method: Initialize
' Description: This is the constructor
' Parameters:
' NetworkName: NetConnectionId for Win 2003, AdapterId - 2008 and Higher
'======================================================================
Public Function Initialize(ByVal NetworkName,ByVal AdapterId ,ByVal discoverUnusedNetworks,ByVal IsGuid)

Dim sFilter
Dim IsError
Dim result
Dim message
Dim deviceIdp
Dim Count
Dim NicGuid

result = false
Initialize = result

Call Clear()

sFilter = GetQueryFilter(NetworkName,AdapterId,discoverUnusedNetworks)
If (0 = Len(sFilter)) Then
Initialize = True
Exit Function
End If

'Starting only on Cluster Node Instance so using "." as ComputerName
Dim WMISet, owObj

On Error Resume Next

Set WMISet = g_oClusterUtil.WMIGetInstances(NameSpace, sFilter)
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(WMISet)) ) Then
Set WMISet = Nothing
Exit Function
End If

Count = WMISet.Count
If (0 &lt;&gt; Err.Number) Then
Set WMISet = Nothing
Exit Function
End If

DeviceIdp = "DeviceId"

If (True = HasValue(IsGuid) and (True = IsGuid)) Then
DeviceIdp = "GUID"
End If

'If result set is empty because some Core Has empty Guid
If (0 = Count) Then
IsError = False
Set WMISet = Nothing
If (Len(AdapterId) &lt;= 2) Then
Initialize = True
Exit Function
End If

Set WMISet = GetNicForCore(AdapterId, discoverUnusedNetworks, IsError)
If (False = IsError) Then
If (False = HasValue(WMISet)) Then
Initialize = True
Exit Function
End If
Else
Initialize = False
Exit Function
End If
End If

result = true

For Each owObj In WMISet

deviceID = g_oClusterUtil.WMIGetStringProperty(owObj,deviceIDp,IsError )

adapterType = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(owObj, "AdapterType" , IsError ),DefaultStringMaxSize)
index = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(owObj, "Index" , IsError ),DefaultStringMaxSize)
manufacturer = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(owObj, "Manufacturer", IsError ),DefaultStringMaxSize)
macAddress = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(owObj, "MACAddress" , IsError ),DefaultStringMaxSize)
serviceName = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(owObj, "ServiceName" , IsError ),DefaultStringMaxSize)
macAddress = Replace(macAddress, ":", "-")

Exit For
Next

If (0 &lt;&gt; Len(Trim(index)) ) Then
Call GetNicInfo(index)
End If

Set owObj = Nothing
Set WMISet = Nothing

Initialize = result
End Function

'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal clusterKey _
,ByVal networkItfKey _
,ByRef oObject _
,ByRef oDiscoveryData _
,ByVal ComputerName _
,ByVal NetworkInterfaceTypeGuid _
,ByVal networkInterfacePropClusterNameGuid _
,ByVal networkInterfacePropNameGuid _
,ByVal strNetworkInterfacePropClusterAdapterID _
,ByRef IsFound _
)

Dim result
Dim adapter
Dim address
Dim name
Dim strClusterAdapterID
Dim oInstance
Dim IsError

result = false
DiscoverInstance = result
IsFound = False

If (0 = Len(deviceID)) Then
DiscoverInstance = True
Exit Function
End If
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for " &amp; networkInterfaceTypeGuid

On Error Resume Next

adapter = g_oClusterUtil.WMIGetStringProperty (oObject, "Adapter" , IsError )
address = g_oClusterUtil.WMIGetStringProperty ( oObject, "Address" , IsError)
name = g_oClusterUtil.WMIGetStringProperty ( oObject, "DeviceID" , IsError)

If (0 = Len(description)) Then
description = adapter
End If

If (0 = Len(IPAddress)) Then
IPAddress = address
IPAddress = g_oUtil.GetStringProperty(address ,DefaultStringMaxSize)
End If

adapter = g_oUtil.GetStringProperty(adapter ,DefaultStringMaxSize)
description = g_oUtil.GetStringProperty(description,DefaultStringMaxSize)
name = g_oUtil.GetStringProperty(name ,DefaultStringMaxSize)

Call Err.Clear()
IsError = False


Set oInstance = oDiscoveryData.CreateClassInstance(networkInterfaceTypeGuid)
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(oInstance)) ) Then
Exit Function
End If


With oInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
ComputerName
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", _
g_oUtil.GetStringProperty(deviceID,DefaultStringMaxSize)
.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
g_oUtil.GetStringProperty(networkItfKey,DefaultStringMaxSize)
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Name$", _
adapter
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
description
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/IPAddress$", _
IPAddress
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/IPSubnet$", _
IPSubnet
.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 _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/DHCPEnabled$", _
DHCPEnabled
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/DHCPServer$", _
DHCPServer
.AddProperty _
"$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/DNSDomain$", _
DNSDomain
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.NetworkAdapter']/IPEnabled$", _
IpEnabled
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.NetworkAdapter']/DefaultIPGateway$", _
DefaultIPGateway

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

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

strClusterAdapterID = g_oUtil.GetStringProperty(GetAdapterId(oObject),DefaultStringMaxSize)

If (Len(strClusterAdapterID) &gt; 0 and Len(strNetworkInterfacePropClusterAdapterID) &gt; 0) Then
.AddProperty _
strNetworkInterfacePropClusterAdapterID, strClusterAdapterID
End If

End With

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance(oInstance)
result = (0 = Err.number)
IsFound = True


DiscoverInstance = result

End Function

Private Function GetAdapterId(oObject)

GetAdapterId = ""

If (False = HasValue(oObject)) Then
Exit Function
End If

Dim AdapterId

On Error Resume Next
Err.Clear
AdapterId = oObject.AdapterId

If (0 = Err.number) Then
AdapterId = Replace(AdapterId, "{", "")
AdapterId = Replace(AdapterId, "}", "")
GetAdapterId = AdapterId
End if

On Error Goto 0
End Function

Private Sub GetNicInfo(Index)

If (False = HasValue(Index)) Then
Exit Sub
End If

Dim sFilter,IsError
Dim WMISet, oObj
DIm Count

sFilter = "Win32_NetworkAdapterConfiguration where Index = " &amp; Index

Set WMISet = g_oClusterUtil.WMIGetInstances(NameSpace, sFilter)
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(WMISet)) ) Then
Set WMISet = Nothing
Call Err.Clear()
Exit Sub
End If

On Error Resume Next
Count = WMISet.Count

If ( (0 &lt;&gt; Err.Number) Or (0 = Count) ) Then
Set WMISet = Nothing
Call Err.Clear()
Exit Sub
End If

For Each oObj In WMISet

DHCPEnabled = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "DHCPEnabled" , IsError ),DefaultStringMaxSize)
IPAddress = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "IPAddress" , IsError ),DefaultStringMaxSize)
IPSubnet = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "IPSubnet" , IsError ),DefaultStringMaxSize)
DNSDomain = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "DNSDomain" , IsError ),DefaultStringMaxSize)
DHCPServer = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "DHCPServer" , IsError ),DefaultStringMaxSize)
IpEnabled = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "IPEnabled" , IsError ),DefaultStringMaxSize)
DefaultIPGateway = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty(oObj, "DefaultIPGateway" ,IsError ),DefaultStringMaxSize)

If (0 = Len(IpEnabled) And 0 &lt;&gt; Len(IPAddress) ) Then
IpEnabled = "True"
End If
Exit For
Next

Set WMISet = Nothing
Set oObj = Nothing
On Error Goto 0
End Sub

Private Sub Clear()
deviceID = ""
adapterType = ""
index = ""
manufacturer = ""
macAddress = ""
serviceName = ""
description = ""
DHCPEnabled = ""
IPAddress = ""
IPSubnet = ""
DNSDomain = ""
DHCPServer = ""
IpEnabled = ""
DefaultIPGateway = ""


End Sub

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
NameSpace = "winmgmts:\\.\root\cimv2"

End Sub

Private Function GetQueryFilter(ByVal NetworkName,ByRef AdapterId,ByVal discoverUnusedNetworks)
On Error Resume Next

Dim sFilter

sFilter = ""
GetQueryFilter = sFilter

If ( (False = HasValue(NetworkName)) and (False = HasValue(AdapterId)) ) Then
'Nothing to find
Exit Function
End If

AdapterId = Trim(AdapterId)

If ( (0 = Len(NetworkName)) and (0 = Len(AdapterId)) ) Then
Exit Function
End If

If (0 = Len(AdapterId)) Then
NetworkName = Replace(NetworkName,"'","\'")
sFilter = "Win32_NetworkAdapter Where NetConnectionID = '" &amp; NetworkName &amp; "'"
Else
AdapterId = "{" &amp; AdapterId &amp; "}"
sFilter = "Win32_NetworkAdapter Where GUID = '" &amp; AdapterId &amp; "'"
End If

If (False = discoverUnusedNetworks) Then
sFilter = sFilter &amp; " And NetConnectionStatus &lt;&gt; 0"
End If

GetQueryFilter = sFilter
On Error Goto 0
End Function

Private Function GetNicById(ByVal AdapterId,ByRef DevId)
On Error Resume Next

Dim sFilter
Dim WmiSet
Dim result
Dim Count
Dim NicCfg
Dim NicId
Dim IsError

DevId = ""
result = False
GetNicById = result
sFilter = "Win32_NetworkAdapterConfiguration where SettingID ='" &amp; AdapterId &amp; "'"
Set WmiSet = g_oClusterUtil.WMIGetInstances(NameSpace, sFilter)

If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(WmiSet)) ) Then
Set WmiSet = Nothing
Exit Function
End If

Count = WMISet.Count
If (0 &lt;&gt; Err.Number) Then
Set WmiSet = Nothing
Exit Function
End If

If (0 = Count) Then
GetNicById = True
Exit Function
End If

NicId = ""
For Each NicCfg in WmiSet
NicId = g_oClusterUtil.WMIGetStringProperty(NicCfg, "Index" , IsError )
Exit For
Next

DevId = NicId
Set NicCfg = Nothing
Set WmiSet = Nothing
GetNicById = True

On Error Goto 0
End Function

Private Function GetNicByIndex(ByVal Index,ByVal discoverUnusedNetworks,ByRef IsError)
On Error Resume Next

Dim sFilter
Dim WmiSet
Dim Count

IsError = False
Set GetNicByIndex = Nothing
sFilter = "Win32_NetworkAdapter where Index = " &amp; Index

If (False = discoverUnusedNetworks) Then
sFilter = sFilter &amp; " And NetConnectionStatus &lt;&gt; 0"
End If

Set WmiSet = g_oClusterUtil.WMIGetInstances(NameSpace, sFilter)
If ( (0 &lt;&gt; Err.Number) Or (False = HasValue(WmiSet)) ) Then
IsError = True
Set WmiSet = Nothing
Exit Function
End If

Count = WMISet.Count
If (0 &lt;&gt; Err.Number) Then
IsError = True
Set WmiSet = Nothing
Exit Function
End If

If (0 &lt;&gt; Count) Then
Set GetNicByIndex = WmiSet
End If

Set WmiSet = Nothing

On Error Goto 0
End Function

Private Function GetNicForCore( ByVal AdapterId, ByVal discoverUnusedNetworks,ByRef IsError)
On Error Resume Next

Dim Index
Dim result

Index = ""
IsError = False
Set GetNicForCore = Nothing

result = GetNicById(AdapterId,Index)

If (False = result) Then
IsError = True
Exit Function
End If

If (0 = Len(Index) ) Then
Exit Function
End If

Set GetNicForCore = GetNicByIndex(Index,discoverUnusedNetworks,IsError)
On Error Goto 0
End Function
End Class ' WinClusterNetworkInterface



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

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

Dim result
On Error Resume Next


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

Call Err.Clear()

Dim oInstance
Dim PostFix

Set DiscoverInstance = Nothing
Set oInstance = oDiscoveryData.CreateClassInstance(discoveryClass)

If ((False = HasValue(oInstance)) Or (0 &lt;&gt; Err.number)) Then
Set oInstance = Nothing
Exit Function
End If

Dim sObjectName,TrimName
Dim DispName

If ((discoveryClass = "$MPElement[Name='Microsoft.Windows.Cluster.Group']$") And (appendClusterNameToResourceGroupName = True)) Then
PostFix = " (" &amp; hostKey &amp; ")"
DispName = GetDispObjectName(ObjectName,PostFix)
Else
DispName = g_oUtil.GetStringProperty(ObjectName,ObjectNameStringMaxSize)
End If

TrimName = Trim(ObjectName)
If (0 = Len(TrimName)) Then
Exit Function
End If

sObjectName = g_oUtil.GetStringProperty(TrimName,ObjectNameStringMaxSize)

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

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

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

End With

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

Set DiscoverInstance = oInstance

End Function


End Class ' WinClusterObject


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

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

' instance
Dim result
Dim clusterHelper
Dim NodeName

result = False
DiscoverInstance = result

On Error Resume Next
Err.Clear
NodeName = ActiveNodesDict.Item(RealGroupName)

If (False = HasValue(NodeName)) Then
NodeName = NetBiosName
Else
If (0 = Len(NodeName)) Then
NodeName = NetBiosName
End If
End If

Set clusterHelper = new WinClusterObject
If ( (False = HasValue(clusterHelper)) Or (0 &lt;&gt; Err.Number) ) Then
Set ClusterHelper = Nothing
Exit Function
End If

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

If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Set ClusterHelper = Nothing
Exit Function
End If

With oInstance

.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.Group']/OriginalGroupName$", _
g_oUtil.GetStringProperty(RealGroupName,ObjectNameStringMaxSize)
.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

'uint32
.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


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

End With

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance(oInstance)
result = (0 = Err.number)
Set oInstance = Nothing
Set ClusterHelper = Nothing


DiscoverInstance = result
End Function


Public Function DiscoverAllResources( _
ByVal hostkey _
,ByVal GroupName _
,ByVal oGroup _
,ByVal GroupType _
,ByVal discoverNonCSVResources _
,ByVal discoverCSVResources _
,ByVal oDiscoveryData _
,ByVal ComputerName _
,ByVal NetBiosName _
,ByVal ClusterNameSpace _
)

On Error Resume Next
Dim result

If (True = discoverNonCSVResources) Then
result = DiscoveryResources(hostkey,GroupName,oGroup,discoverNonCSVResources,oDiscoveryData,ComputerName,NetBiosName)
If (False = result) Then
DiscoverAllResources = result
Exit Function
End If
End If

If (True = discoverCSVResources) Then
result = DiscoveryCSVResources(hostkey,GroupName,GroupType,discoverCSVResources,oDiscoveryData,ComputerName,NetBiosName,ClusterNameSpace)
End If

DiscoverAllResources = result
End Function

Private Function DiscoveryResources( _
ByVal hostkey _
,ByVal GroupName _
,ByVal oGroup _
,ByVal discoverNonCSVResources _
,ByVal oDiscoveryData _
,ByVal ComputerName _
,ByVal NetBiosName _
)
On Error Resume Next

Dim result

result = False
DiscoveryResources = result

Dim oResources
Dim Query
Dim oResource
Dim oRealResource
Dim oWinClusterResource
Dim Count


GroupName = Trim(GroupName)
If (0 = Len(GroupName) ) Then
Exit Function
End If

Set oWinClusterResource = new WinClusterResource
If (0 &lt;&gt; Err.number) Then
Set oWinClusterResource = Nothing
Exit Function
End If

Set oResources = oGroup.Associators_("MSCluster_ResourceGroupToResource", "", "", "", False, False, "", "", 0)

If (0 &lt;&gt; Err.number) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing
Exit Function
End If

Count = oResources.Count
If (0 &lt;&gt; Err.number) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing
Exit Function
End If

If (0 = Count) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing
DiscoveryResources = true
Exit Function
End If

result = true
For Each oResource in oResources

result = oWinClusterResource.DiscoverInstance ( _
hostKey _
,GroupName _
,oResource _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
)

If (false = result) Then
Exit For
End If

Next

Set oResource = Nothing
Set oResources = Nothing
Set oWinClusterResource = Nothing
DiscoveryResources = result
End Function

Private Function DiscoveryCSVResources( _
ByVal hostkey _
,ByVal GroupName _
,ByVal GroupType _
,ByVal discoverCSVResources _
,ByVal oDiscoveryData _
,ByVal ComputerName _
,ByVal NetBiosName _
,ByVal ClusterNameSpace _
)
On Error Resume Next

Dim result
Dim Count

result = False
DiscoveryCSVResources = result

Dim oResources
Dim Query
Dim oResource
dim oWinClusterResource
Dim boolDiscoverCSV

GroupName = Trim(GroupName)
If (0 = Len(GroupName) ) Then
Exit Function
End If

boolDiscoverCSV = IsDiscoverCSVresource(GroupType,GroupName)

If (False = boolDiscoverCSV) Then
DiscoveryCSVResources = True
Exit Function
End If

Set oWinClusterResource = new WinClusterResource
If (0 &lt;&gt; Err.number) Then
Set oWinClusterResource = Nothing
Exit Function
End If

Query = "select * from MSCluster_Resource where IsClusterSharedVolume = true"
Set oResources = g_oClusterUtil.WMIExecQueryNoAbort (ClusterNameSpace, Query)

If (0 &lt;&gt; Err.number) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing

'Pre Windows 2008 r2
If (WMI_INVALID_QUERY = Err.number) Then
DiscoveryCSVResources = True
Call Err.Clear()
End If

Exit Function
End If

Count = oResources.Count
If (0 &lt;&gt; Err.number) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing
Exit Function
End If

If (0 = Count) Then
Set oResources = Nothing
Set oWinClusterResource = Nothing
DiscoveryCSVResources = True
Exit Function
End If

result = true
For Each oResource in oResources

result = oWinClusterResource.DiscoverInstance ( _
hostKey _
,GroupName _
,oResource _
,oDiscoveryData _
,ComputerName _
,NetBiosName _
)

If (false = result) Then
Exit For
End If

Next

Set oResource = Nothing
Set oResources = Nothing
Set oWinClusterResource = Nothing

DiscoveryCSVResources = result
End Function

Private Function IsDiscoverCSVresource(GroupType,GroupName)

IsDiscoverCSVresource = False

If (True = IsNull(GroupType)) Then
If (LCase(GroupName) = "cluster group" ) Then
IsDiscoverCSVresource = True
End If
Else
If (1 = GroupType) Then
IsDiscoverCSVresource = True
End If
End If

End Function

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

On Error Resume Next
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for cluster contains groups."

Call Err.Clear()

Dim result
Dim sgroupKey

result = false
DiscoverClusterContainsRelationship = result

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Group']$")
If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Exit Function
End If

sgroupKey = g_oUtil.GetStringProperty(Trim(groupKey),ObjectNameStringMaxSize)

With oInstance

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

End With

If (0 &lt;&gt; Err.Number ) Then
Set oInstance = Nothing
Exit Function
End If

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

Set oInstance = Nothing
DiscoverClusterContainsRelationship = result

End Function

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

' instance
On Error Resume Next

Dim result
Dim sGroupName
Dim DisplayName
Dim PostFix
Dim TrimGroupName

result = false

DiscoverInstanceForHosted = result
TrimGroupName = g_oUtil.GetStringProperty(Trim(GroupName),ObjectNameStringMaxSize)
sGroupName = g_oUtil.GetStringProperty(GroupName,ObjectNameStringMaxSize)
PostFix = " (" &amp; hostKey &amp; " )" &amp; " (" &amp; NetBiosName &amp; ")"
DisplayName = GetDispObjectName(TrimGroupName,PostFix)

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

If ( (False = HasValue(oHostedGroupInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oHostedGroupInstance = Nothing
Exit Function
End If

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

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

.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$", _
TrimGroupName

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


.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

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance(oHostedGroupInstance)
result = (0 = Err.number)

DiscoverInstanceForHosted = result

End Function

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

On Error Resume Next
Dim result
Dim TrimGroupKey

result = False
DiscoverClusterGroupContainsRelationship = result

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

Call Err.Clear()

Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Group']$")
If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Exit Function
End If

TrimGroupKey = g_oUtil.GetStringProperty(Trim(groupKey),ObjectNameStringMaxSize)

With oInstance

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

End With

If ( 0 &lt;&gt; Err.Number ) Then
Set oInstance = Nothing
Exit Function
End If


Dim oHostedInstance
Set oHostedInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$")
If ( (False = HasValue(oHostedInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Set oHostedInstance = Nothing
Exit Function
End If

With oHostedInstance

.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
ComputerName
.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$", _
TrimGroupKey

End With

If (0 &lt;&gt; Err.Number ) Then
Set oInstance = Nothing
Set oHostedInstance = Nothing
Exit Function
End If

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

If ( (False = HasValue(oRelationshipInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Set oHostedInstance = Nothing
Set oRelationshipInstance = Nothing
Exit Function
End If

oRelationshipInstance.Source = oInstance
oRelationshipInstance.Target = oHostedInstance

If (0 &lt;&gt; Err.Number ) Then
Set oInstance = Nothing
Set oHostedInstance = Nothing
Set oRelationshipInstance = Nothing
Exit Function
End If

Call oDiscoveryData.AddInstance(oRelationshipInstance)
result = (0 = Err.number)

Set oInstance = Nothing
Set oHostedInstance = Nothing
Set oRelationshipInstance = Nothing

DiscoverClusterGroupContainsRelationship = result
End Function

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 _
,ByVal ComputerName _
,ByVal NetBiosName _
)
On Error Resume Next

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

Dim ResourceName
Dim TrimResourceName
Dim lResourceName
Dim sgroupKey
Dim typeName
Dim description
Dim isAlivePollInterval
Dim LooksAlivePollInterval
Dim pendingTimeout
Dim persistentState
Dim restartAction
Dim restartPeriod
Dim restartThreshold
Dim retryPeriodOnFailure
Dim separateMonitor
Dim defaultValue
Dim IsError
Dim result
Dim DispName
Dim TrimName

result = false
DiscoverInstance = result
defaultValue = -1

Call Err.Clear()
sgroupKey = g_oUtil.GetStringProperty(groupKey,ObjectNameStringMaxSize)
lResourceName = g_oClusterUtil.WMIGetStringProperty ( oObject, "Name" , IsError)
DispName = g_oUtil.GetStringProperty(lResourceName,ObjectNameStringMaxSize)
TrimName = Trim(lResourceName)
ResourceName = g_oUtil.GetStringProperty(TrimName,ObjectNameStringMaxSize)
lResourceName = DispName

If (0 = Len(TrimName)) Then
Exit Function
End If

typeName = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "Type" , IsError),DefaultStringMaxSize)
description = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "Description", IsError),DefaultStringMaxSize)

isAlivePollInterval = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "IsAlivePollInterval" , defaultValue, IsError)
looksAlivePollInterval = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "LooksAlivePollInterval", defaultValue, IsError)
pendingTimeout = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "PendingTimeout" , defaultValue, IsError)
restartAction = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "RestartAction" , defaultValue, IsError)
restartPeriod = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "RestartPeriod" , defaultValue, IsError)
restartThreshold = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "RestartThreshold" , defaultValue, IsError)
retryPeriodOnFailure = g_oClusterUtil.WMIGetIntegerProperty ( oObject, "RetryPeriodOnFailure" , defaultValue, IsError)

persistentState = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "PersistentState", IsError),DefaultStringMaxSize)
separateMonitor = g_oUtil.GetStringProperty(g_oClusterUtil.WMIGetStringProperty ( oObject, "SeparateMonitor", IsError),DefaultStringMaxSize)

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

If ( (False = HasValue(oInstance)) Or (0 &lt;&gt; Err.Number) ) Then
Set oInstance = Nothing
Exit Function
End If


With oInstance

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

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

.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$", _
sgroupKey

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

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

.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

If (0 &lt;&gt; Err.number) Then
Exit Function
End If

Call oDiscoveryData.AddInstance(oInstance)
result = (0 = Err.number)

DiscoverInstance = result

End Function

End Class ' WinClusterResource

</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>vbparams.txt</Name>
<Contents><Script>"$Config/DiscoverySourceId$" "$Target/Id$" "$Config/ComputerName$" "$Config/NetBiosName$" "$Config/DiscoverUnusedNetworks$" "$Config/NetworkContainsInterfaceGuid$" "$Config/NetworkInterfaceTypeGuid$" "$Config/NetworkInterfacePropClusterNameGuid$" "$Config/NetworkInterfacePropNameGuid$" "$Config/DiscoverCSVResources$" "$Config/DiscoverNonCSVResources$" "$Config/ResourceGroupDiscoveryLimit$" "$Config/AppendClusterNameToResourceGroupName$" "$Config/NetworkInterfacePropClusterAdapterID$" "$Config/ResourceGroupTypeFilter$" "$Config/OSVersion$"</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>psparams.txt</Name>
<Contents><Script>'$Config/DiscoverySourceId$' '$Target/Id$' '$Config/ComputerName$' '$Config/NetBiosName$' '$Config/DiscoverUnusedNetworks$' '$Config/NetworkContainsInterfaceGuid$' '$Config/NetworkInterfaceTypeGuid$' '$Config/NetworkInterfacePropClusterNameGuid$' '$Config/NetworkInterfacePropNameGuid$' '$Config/DiscoverCSVResources$' '$Config/DiscoverNonCSVResources$' '$Config/ResourceGroupDiscoveryLimit$' '$Config/AppendClusterNameToResourceGroupName$' '$Config/NetworkInterfacePropClusterAdapterID$' '$Config/ResourceGroupTypeFilter$' '$Config/OSVersion$'</Script></Contents>
<Unicode>false</Unicode>
</File>
</Files>
<OutputType>System.Discovery.Data</OutputType>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="Script"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>