Const EVENT_ID_SUCCESS = 1000 'Use IDs in the range 1 - 1000
Const EVENT_ID_SCRIPTERROR = 999 'Then you can use eventcreate.exe to test the MP
Const SCRIPT_SUCCESS = 0
Const SCRIPT_WITH_ERROR = 1
'Global vars
Dim mblnLogSuccessEvent 'As Boolean
Dim mstrIdentifier 'As String
Call Main
'*********************************************************************************************
' PROCEDURE: Main
' DESCRIPTION: Reads the script parameters and creates the cluster shared volume discovery data.
' PARAMETERS: void
'*********************************************************************************************
Private Sub Main()
' Targeted at Microsoft.Windows.Cluster.VirtualServer (based on Microsoft.Windows.Server.Computer)
Dim strSourceID 'As String '= oArgs(4). strSourceId is the GUID of the discovery object that runs the script ($MPElement$).
Dim strManagedEntityId 'As String '= oArgs(5) - strManagedEntityId is the GUID of the computer class that is targeted by the script ($Target/Id$).
Dim strTargetComputer 'As String '= oArgs(6)
Dim strClusterName 'As String '= oArgs(7)
Dim objMomScriptAPI 'As MOM.ScriptAPI
Dim objDiscoveryData 'As DiscoveryData
Dim intSuccess 'As Integer
Dim strErrorMessage
On Error Resume Next
Err.Clear
Set objMomScriptAPI = CreateObject("MOM.ScriptAPI")
If Err.Number <> 0 Then
WScript.Quit(-1)
End If
If Not GetClusterName(strClusterName) Then
WScript.Quit(-1)
End If
If Not GetScriptParameters(strSourceID, strManagedEntityId, strTargetComputer) Then
' If the script is called without the required arguments,
' create an information event and then quit.
strErrorMessage = "The script was called with fewer than five arguments or the arguments could not be parsed"
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
WScript.Quit(-1)
End If
'Create new discovery data object
Set objDiscoveryData = objMomScriptAPI.CreateDiscoveryData(0, strSourceID, strManagedEntityId)
If Err.Number <> 0 Then
strErrorMessage = vbCrLf & "The script cannot create Discovery Data"
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
WScript.Quit(-1)
End If
If intSuccess = SCRIPT_SUCCESS Then
If mblnLogSuccessEvent Then
strErrorMessage = vbCrLf & "Script executed successfully."
Call LogScriptEvent(0, EVENT_ID_SUCCESS, EVENT_TYPE_INFORMATION, strErrorMessage,objMomScriptAPI)
End If
'Return discovery data
Call objMomScriptAPI.Return(objDiscoveryData)
Else
strErrorMessage = vbCrLf & "An error occurred while running the script."
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
End If
Set objDiscoveryData = Nothing
Set objMomScriptAPI = Nothing
On Error Goto 0
End Sub
'****************************************************************************************************************
' FUNCTION: DiscoverClusterSharedVolumes
' DESCRIPTION: Discover instances of the class 'Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume' using WMI.
' PARAMETERS: IN String strTargetComputer: principal name of the targeted 'Microsoft.Windows.Cluster.VirtualServer' instance.
' IN String strClusterName: the cluster containing the cluster shared volume
' OUT Object objDiscoveryData: initialised DiscoveryData instance
' RETURNS: Integer: 0 if successful and 1 if fails
'****************************************************************************************************************
Private Function DiscoverClusterSharedVolumes(ByRef strTargetComputer, ByRef strClusterName, ByRef objDiscoveryData) 'As Integer
Dim objMSClusterSWbemServices 'As SWbemServices
Dim objClusterSharedVolumes 'As SWbemObjectSet
Dim objClusterSharedVolume 'As SWbemObject
Dim objClusterDiskPartition 'As SWbemObject
Dim objClusterDiskPartitions 'As SWbemObject
Dim objClusterResource 'As SWbemObject
Dim objClusterResources 'As SWbemObject
Dim intSuc 'As Integer
Dim blnCreateDiscoveryData
Dim strComputerName
Dim bValidObjects
If strComputerName = LCase(strClusterName) Then
blnCreateDiscoveryData = True
Else
DiscoverClusterSharedVolumes = SCRIPT_SUCCESS
Exit Function
End If
On Error Resume Next
Set objClusterSharedVolumes = objMSClusterSWbemServices.ExecQuery("select * from " & WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME)
If (Err.number <> 0 ) Then
Exit Function
End If
If (Not HasValue(objClusterSharedVolumes) ) Then
DiscoverClusterSharedVolumes = SCRIPT_SUCCESS
Exit Function
End If
'Loop through all returned cluster shared volumes
For Each objClusterSharedVolume In objClusterSharedVolumes
If (Err.Number <> 0) Then
'Class Doesn't exist. Return Empty Discovery Data
If (-2147217392 = Err.Number) Then
DiscoverClusterSharedVolumes = SCRIPT_SUCCESS
End If
Set objClusterSharedVolumes = Nothing
Exit Function
End If
'Get the associated disk partition
Set objClusterDiskPartitions = objClusterSharedVolume.Associators_(WMI_CLUSTER_SHARED_VOLUME_TO_PARTITION_ASSOCIATOR_CLASS, "", "", "", False, False, "", "", 0)
Set objClusterResources = objClusterSharedVolume.Associators_(WMI_CLUSTER_SHARED_VOLUME_TO_RESOURCE_ASSOCIATOR_CLASS, "", "", "", False, False, "", "", 0)
bValidObjects = Not (HasValue(objClusterDiskPartitions) And HasValue(objClusterResources))
If (Err.Number <> 0) Then
Set objClusterSharedVolumes = Nothing
Set objClusterDiskPartitions = Nothing
Set objClusterResources = Nothing
Exit Function
End If
If (bValidObjects = True) Then
Set objClusterSharedVolumes = Nothing
Set objClusterDiskPartitions = Nothing
Set objClusterResources = Nothing
DiscoverClusterSharedVolumes = SCRIPT_SUCCESS
Exit Function
End If
'Get the associated disk partition
For Each objClusterDiskPartition In objClusterDiskPartitions
'Get the associated resource
If (Err.Number <> 0) Then
Set objClusterSharedVolumes = Nothing
Set objClusterDiskPartitions = Nothing
Set objClusterResources = Nothing
Exit Function
End If
For Each objClusterResource In objClusterResources
If (Err.Number <> 0) Then
Set objClusterSharedVolumes = Nothing
Set objClusterDiskPartitions = Nothing
Set objClusterResources = Nothing
Exit Function
End If
intSuc = CreateDiscoveryData(objClusterSharedVolume, objClusterDiskPartition, objClusterResource,strTargetComputer, strClusterName, objDiscoveryData)
If (SCRIPT_WITH_ERROR = intSuc) Then
blnCreateDiscoveryData = False
End If
Next 'objClusterResource
Next 'objClusterDiskPartition
If Err.Number <> 0 Then
blnCreateDiscoveryData = False
DiscoverClusterSharedVolumes = SCRIPT_WITH_ERROR
Exit Function
End If
Next 'objClusterSharedVolume
If blnCreateDiscoveryData Then
DiscoverClusterSharedVolumes = SCRIPT_SUCCESS
End If
On Error Goto 0
End Function
'****************************************************************************************************************
' FUNCTION: CreateDiscoveryData
' DESCRIPTION: Create discovery data for
' <ClassType ID="Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume" Accessibility="Internal" Abstract="false" Base="Windows!Microsoft.Windows.ApplicationComponent" Hosted="true" Singleton="false">
' <Property ID="ClusterSharedVolumeName" Type="string" Key="true" CaseSensitive="false" Length="256" MinLength="0" />
' <Property ID="FriendlyVolumeName" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
' <Property ID="PartitionName" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
' <Property ID="PartitionFileSystem" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
' <Property ID="PartitionSize" Type="int" Key="false" />
' <Property ID="ClusterName" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
' <Property ID="VolumeLabel" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
' </ClassType>
'
' PARAMETERS: IN Object objClusterSharedVolume: the cluster shared volume as SWbemObject of type MSCluster_ClusterSharedVolume.
' IN Object objClusterDiskPartition: the associated disk partition as SWbemObject of type MSCluster_DiskPartition.
' IN Object objClusterResource: the associated cluster resource as SWbemObject of type MSCluster_Resource.
' IN String strTargetComputer: the principal name of the targeted cluster virtual server hosting the cluster shared volume,
' i.e. the cluster name and not the current owner!
' IN String strClusterName: the cluster containing the cluster shared volume
' OUT Object objDiscoveryData: initialised DiscoveryData instance
' RETURNS: Integer: 0 if successful or 1 if Error
'****************************************************************************************************************
Private Function CreateDiscoveryData(ByRef objClusterSharedVolume, ByRef objClusterDiskPartition, ByRef objClusterResource,ByRef strTargetComputer, ByRef strClusterName, ByRef objDiscoveryData) 'As Integer
Dim objCSVInstance 'As MOMClassInstance
Dim strCSVName
On Error Resume Next
CreateDiscoveryData = SCRIPT_WITH_ERROR
Err.Clear
If (False = HasValue(objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME)) Or False = HasValue(objClusterSharedVolume.Properties_(WMI_NAME_PROPERTY_NAME)) ) Then
On Error Goto 0
Exit Function
End If
strCSVName = objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME) & "_" & objClusterSharedVolume.Properties_(WMI_NAME_PROPERTY_NAME)
If ( Len(strCSVName) > MAX_FIELD_LENGTH) Then
strCSVName = Left(strCSVName,MAX_FIELD_LENGTH)
End If
'Create the cluster shared volume instance hosted on the targeted cluster virtual server
Set objCSVInstance = objDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume.LegacyOS']$")
If (0 = Err.number) Then
Call objDiscoveryData.AddInstance(objCSVInstance)
If (0 = Err.number) Then
CreateDiscoveryData = SCRIPT_SUCCESS
End If
End If
Set objCSVInstance = Nothing
On Error Goto 0
End Function
'******************************************************************************
' FUNCTION: GetScriptParameters
' DESCRIPTION: Reads the script's parameters
' and sets the global variables.
'
' PARAMETERS: OUT String strSourceID: Id of MP element ($MPElement$)
' OUT String strManagedEntityId: Id of targeted entity ($Target/Id$)
' OUT String strTargetComputer: Principal name of executing computer
' (-Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName-)
' OUT String strClusterName: Cluster name
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function GetScriptParameters(ByRef strSourceID, ByRef strManagedEntityId, ByRef strTargetComputer) 'As Boolean
Dim objArguments
On Error Resume Next
'cmdline: <script> True|False <path to debug log> True|False <script id> .MPElement. .Target/Id. .Target/Host/Property[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName.
Set objArguments = WScript.Arguments
If objArguments.Count < 5 Then Exit Function
Err.Clear
'Get parameters and set global variables
mblnLogSuccessEvent = CBool(objArguments(0))
If (Err.Number <> 0 ) Then
mblnLogSuccessEvent = False
End If
mstrIdentifier = Replace(objArguments(1), Chr(34), "")
strSourceID = Replace(objArguments(2), Chr(34), "")
strManagedEntityId = Replace(objArguments(3), Chr(34), "")
strTargetComputer = Replace(objArguments(4), Chr(34), "")
If Len(strSourceID) > 0 And Len(strManagedEntityId) > 0 And Len(strTargetComputer) > 0 Then GetScriptParameters = True
On Error Goto 0
End Function
'****************************************************************************************************************
' FUNCTION: GetClusterName
' DESCRIPTION: Returns the cluster name of the given cluster virtual name
' PARAMETERS: OUT String strClusterName: string to return the cluster name
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function GetClusterName(ByRef strClusterName) 'As Boolean
Dim objMSClusterSWbemServices 'As SWbemServices
Dim strWQLQuery 'As String
Dim objClusters 'As SWbemObjectSet
Dim objCluster 'As SWbemObject
Dim bResult
If (True = bResult And Len(strClusterName) > 0 ) Then
GetClusterName = bResult
Exit Function
End If
On Error Resume Next
Err.Clear
'Connect to WMI NS \\.\root\MSCluster
If ConnectToWbemNS(".", WMI_MSCLUSTER_NAMESPACE, objMSClusterSWbemServices) Then
strWQLQuery = "select * from " & WMI_MSCLUSTER_CLUSTER_CLASS
Set objClusters = objMSClusterSWbemServices.ExecQuery(strWQLQuery)
If HasValue(objClusters) Then
For Each objCluster In objClusters
strClusterName = objCluster.Name
Next 'objCluster
If Len(strClusterName) > 0 Then GetClusterName = True
End If
Set objClusters = Nothing
End If
On Error Goto 0
End Function
'****************************************************************************************************************
' FUNCTION: GetClusterNameFromRegistry
' DESCRIPTION: Returns the cluster name of the given cluster virtual name
' PARAMETERS: OUT String strClusterName: string to return the cluster name
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function GetClusterNameFromRegistry(ByRef strClusterName) 'As Boolean
Dim objReg 'Registry
Const ClusterNamePath = "HKLM\Cluster\ClusterName"
strClusterName = ""
GetClusterNameFromRegistry = False
On Error Resume Next
Err.Clear
Set objReg = CreateObject("WScript.Shell")
strClusterName = objReg.RegRead(ClusterNamePath)
If (0 = Err.Number ) Then
GetClusterNameFromRegistry = True
End If
Set objReg = Nothing
On Error Goto 0
End Function
'****************************************************************************************************************
' FUNCTION: GetComputerName ' DESCRIPTION: return short computername
' PARAMETERS: IN String strTargetComputer: principal name of the targeted 'Microsoft.Windows.Cluster.VirtualServer' instance.
' RETURNS: Integer: 0 if successful and 1 if fails
'****************************************************************************************************************
Private Function GetComputerName(strTargetComputer)
Dim strComputerName
Dim PointPos
PointPos = InStr(strTargetComputer, ".")
If PointPos > 0 Then
strComputerName = LCase(Left(strTargetComputer, PointPos - 1))
Else
strComputerName = LCase(strTargetComputer)
End If
GetComputerName = strComputerName
End Function
'******************************************************************************
' FUNCTION: ConnectToWbemNs
' DESCRIPTION: Connects to a WMI namespace
' PARAMETERS: IN String strServerName: name of the computer. If empty the local computer will be used.
' IN String strNameSpace: WMI namespace
' OUT Object objSWbemServices: WbemScripting.SWbemServices object connected to the given
' namespace on the given server
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function ConnectToWbemNS(ByRef strServerName, ByRef strNameSpace, ByRef objSWbemServices) 'As Boolean
ConnectToWbemNS = False
Dim objSWbemLocator 'as WbemScripting.SWbemLocator
On Error Resume Next
'Create a new WMI Locator object
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
IF HasValue(objSWbemLocator) Then
'Connect to WMI namespace on strServerName computer and create WMI Services object
Set objSWbemServices = objSWbemLocator.ConnectServer(strServerName, strNameSpace)
END IF
'If object is initialised function will be successful
ConnectToWbemNS = HasValue(objSWbemServices)
On Error Goto 0
End Function
Private 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
Private Function GetLogScriptName()
GetLogScriptName = "-- Cluster Shared Volumes Cluster Discovery Script -- " & vbCrLf & vbCrLf & "Script name: " & WScript.ScriptName & vbCrLf & "Version: " & SCRIPT_VERSION & vbCrLf
End Function
'******************************************************************************
' Subroutine: LogScriptEvent
' DESCRIPTION: Logging events to EventSource
' PARAMETERS: IN Integer LogType: 0 - MomScriptApi; 1 - File, 2 - Screen .
' IN String Message: Event Description
' OUT Object objSWbemServices: WbemScripting.SWbemServices object connected to the given
' namespace on the given server
' RETURNS: Boolean: True if successful
'******************************************************************************
Sub LogScriptEvent(LogType,EventId,EventLevel,Message,objMomScriptAPI)
Dim strMessage
Dim sDate
Dim LogScriptName
On Error Resume Next
If (0 = LogType) Then
If (Not HasValue(objMomScriptAPI)) Then
Exit Sub
End If
LogScriptName = GetLogScriptName()
Call objMomScriptAPI.LogScriptEvent(LogScriptName,EventId,EventLevel,Message)
Else
sDate = Now()
strMessage = "" & sDate & Message
If (1 = LogType) Then
WScript.Echo strMessage
End If
End If
On Error Goto 0
End Sub </Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="VbProbe">
<Node ID="DS"/>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>