SMS 2003 Monitor Management Point Health

SMS_2003_Monitor_Management_Point_Health (WriteActionModuleType)

Determines the Health State of the SMS 2003 Management Point

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
InputTypeSystem.BaseData
Comment{203B6A27-D297-40D5-A33F-6ABAF6254282}

Member Modules:

ID Module Type TypeId RunAs 
RunScriptAction WriteAction System.Mom.BackwardCompatibility.ScriptResponse Default

Source Code:

<WriteActionModuleType ID="SMS_2003_Monitor_Management_Point_Health" Accessibility="Internal" Comment="{203B6A27-D297-40D5-A33F-6ABAF6254282}">
<Configuration>
<IncludeSchemaTypes>
<SchemaType>MomBackwardCompatibility!System.Mom.BackwardCompatibility.AlertGenerationSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="AlertGeneration" type="AlertGenerationType"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="InvokerType" type="xsd:integer"/>
</Configuration>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="RunScriptAction" TypeID="MomBackwardCompatibility!System.Mom.BackwardCompatibility.ScriptResponse">
<AlertGeneration>$Config/AlertGeneration$</AlertGeneration>
<InvokerType>$Config/InvokerType$</InvokerType>
<Body><Script>
'*******************************************************************************
' Script Name - SMS 2003 Monitor Management Point Health
'
' Purpose - Monitors the health of SMS 2003 Management Point Servers. The
' health state is reported through Parameter 1 of event
'
' 1700 - An event used to report Management Point health state.
'
' Paramter 1
' (Health State) Condition
' -------------- ---------
' 0 Healthy
' 1 Unhealthy
'
' The following additional events can be raised:
'
' 1100 - An event used only for debugging or tracing.
' 1101 - Script executed successfully.
' 1102 - An error occurred in executing this script.
' 1105 - Accessed denied due to connection failure or permissions.
'
' Assumptions - This script will only run on SMS 2003 Management Point Servers.
' Builds earlier than 02.50.3067.0000 do not support Health State
' and consequently can not be monitored.
'
' Parameters - None
'
' Change Hist - Date Version Description
' -------- --------------- -----------
' 03/20/04 02.50.0170.0000 Created
' 05/08/04 02.50.0178.0000 Bug fixes
'
' (c) Copyright 2004, Microsoft Corp., All Rights Reserved
'*******************************************************************************

Option Explicit

'Event Severity Constants
'========================

Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4

Const EVENTLOG_AUDIT_SUCCESS = 8
Const EVENTLOG_AUDIT_FAILURE = 16


'Event Number Constants
'======================

Const EVENT_ID_NOTANEVENT = 1100
Const EVENT_ID_SCRIPTSUCCESS = 1101
Const EVENT_ID_SCRIPTERROR = 1102
Const EVENT_ID_ACCESSDENIED = 1105

Const EVENT_ID_MANAGEMENT_POINT_HEALTH = 1700


'Event and Log Messages Constants
'================================

'Start Localization

Const EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE = "The health state changed for this SMS 2003 Management Point in site "
Const EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE_HEALTHY = " to healthy."
Const EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE_UNHEALTHY = " to unhealthy."

Const WMI_NO_NAMESPACE_SOURCE = "Unable to open WMI Namespace {Namespace}"
Const WMI_NO_NAMESPACE_DESCRIPTION = "Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists. Error:{ErrorNumber}, {ErrorDescription}."

Const WMI_NO_INSTANCES_SOURCE = "The class name '{ClassName}' returned no instances."
Const WMI_NO_INSTANCES_DESCRIPTION = "Please check to see if this is a valid WMI class name. Error:{ErrorNumber}, {ErrorDescription}."

Const WMI_NO_VALID_INSTANCES_SOURCE = "The class name '{ClassName}' did not return any valid instances."
Const WMI_NO_VALID_INSTANCES_DESCRIPTION = "Please check to see if this is a valid WMI class name. Error:{ErrorNumber}, {ErrorDescription}."

Const WMI_QUERY_NO_RESULTS_SOURCE = "The Query '{Query}' returned an invalid result set."
Const WMI_QUERY_NO_RESULTS_DESCRIPTION = "Please check to see if this is a valid WMI Query. Error:{ErrorNumber}, {ErrorDescription}."

Const WMI_QUERY_NO_VALID_INSTANCES_SOURCE = "The Query '{Query}' did not return any valid instances."
Const WMI_QUERY_NO_VALID_INSTANCES_DESCRIPTION = "Please check to see if this is a valid WMI Query. Error:{ErrorNumber}, {ErrorDescription}."
'End Localization


'Varset Constants
'================

Const VARSET_NAME = "SMS 2003 Monitor Management Point Health"

Const VARSET_VAR_HEALTH_STATE = "Health State"


' Global variables
'=================

Dim g_oUtil ' Utility class for MOM events, logging and registry access.


'******************************************************************************
' Replacement string functions for event and log messages
'
'

Function GET_WMI_NO_NAMESPACE_SOURCE(ByVal sNamespace)
GET_WMI_NO_NAMESPACE_SOURCE = Replace(WMI_NO_NAMESPACE_SOURCE, "{Namespace}", sNamespace)
End Function

Function GET_WMI_NO_NAMESPACE_DESCRIPTION(ByVal lErrorNumber, ByVal sErrorDescription)
Dim sResult
sResult = Replace(WMI_NO_NAMESPACE_DESCRIPTION, "{ErrorNumber}", lErrorNumber)
GET_WMI_NO_NAMESPACE_DESCRIPTION = Replace(sResult, "{ErrorDescription}", sErrorDescription)
End Function

Function GET_WMI_NO_INSTANCES_SOURCE(ByVal sClassName)
GET_WMI_NO_INSTANCES_SOURCE = Replace(WMI_NO_INSTANCES_SOURCE, "{ClassName}", sClassName)
End Function

Function GET_WMI_NO_INSTANCES_DESCRIPTION(ByVal lErrorNumber, ByVal sErrorDescription)
Dim sResult
sResult = Replace(WMI_NO_INSTANCES_DESCRIPTION, "{ErrorNumber}", lErrorNumber)
GET_WMI_NO_INSTANCES_DESCRIPTION = Replace(sResult, "{ErrorDescription}", sErrorDescription)
End Function

Function GET_WMI_NO_VALID_INSTANCES_SOURCE(ByVal sClassName)
GET_WMI_NO_VALID_INSTANCES_SOURCE = Replace(WMI_NO_VALID_INSTANCES_SOURCE, "{ClassName}", sClassName)
End Function

Function GET_WMI_NO_VALID_INSTANCES_DESCRIPTION(ByVal lErrorNumber, ByVal sErrorDescription)
Dim sResult
sResult = Replace(WMI_NO_VALID_INSTANCES_DESCRIPTION, "{ErrorNumber}", lErrorNumber)
GET_WMI_NO_VALID_INSTANCES_DESCRIPTION = Replace(sResult, "{ErrorDescription}", sErrorDescription)
End Function

Function GET_WMI_QUERY_NO_RESULTS_SOURCE(ByVal sQuery)
GET_WMI_QUERY_NO_RESULTS_SOURCE = Replace(WMI_QUERY_NO_RESULTS_SOURCE, "{Query}", sQuery)
End Function

Function GET_WMI_QUERY_NO_RESULTS_DESCRIPTION(ByVal lErrorNumber, ByVal sErrorDescription)
Dim sResult
sResult = Replace(WMI_QUERY_NO_RESULTS_DESCRIPTION, "{ErrorNumber}", lErrorNumber)
GET_WMI_QUERY_NO_RESULTS_DESCRIPTION = Replace(sResult, "{ErrorDescription}", sErrorDescription)
End Function

Function GET_WMI_QUERY_NO_VALID_INSTANCES_DESCRIPTION(ByVal lErrorNumber, ByVal sErrorDescription)
Dim sResult
sResult = Replace(WMI_QUERY_NO_VALID_INSTANCES_DESCRIPTION, "{ErrorNumber}", lErrorNumber)
GET_WMI_QUERY_NO_VALID_INSTANCES_DESCRIPTION = Replace(sResult, "{ErrorDescription}", sErrorDescription)
End Function

Function GET_WMI_QUERY_NO_VALID_INSTANCES_SOURCE(ByVal sQuery)
GET_WMI_QUERY_NO_VALID_INSTANCES_SOURCE = Replace(WMI_QUERY_NO_VALID_INSTANCES_SOURCE, "{Query}", sQuery)
End Function


'******************************************************************************
' Name: Main
'
' Purpose: Entry point for program execution.
'
' Parameters: None
'
' Returns: Nothing
'
Sub Main()

On Error Resume Next

'Initialize utility object and begin tracing.
'============================================

Set g_oUtil = new Util

g_oUtil.SetDebugLevel g_oUtil.DBG_TRACE

g_oUtil.LogMessage g_oUtil.DBG_TRACE, ScriptContext.Name + " script starting at local time: " + CStr(Time)

'WMI is used by the monitoring functions in this script so check that
'the relevant name spaces are accessible.
'====================================================================

If True &lt;&gt; IsWMIAccessible() Then
Set g_oUtil = Nothing
Exit Sub
End if

'Perform service discovery.
'==========================

CheckHealth

g_oUtil.LogMessage g_oUtil.DBG_TRACE, ScriptContext.Name + " script completed at local time: " + CStr(Time)

Set g_oUtil = Nothing

End Sub


'******************************************************************************
' Name: IsWMIAccessible
'
' Purpose: To determine whether the WMI service is running and accessible
'
' Parameters: None
'
' Returns: Boolean, returns True if the WMI service and root\default namespace
' is accessible.
'
Function IsWMIAccessible()

Dim objService


On Error Resume Next

Err.Clear


Set objService = GetObject("winmgmts:\\" + ScriptContext.TargetComputer + "\root\default")

If Err Then
IsWMIAccessible = False
g_oUtil.LogMessage g_oUtil.DBG_TRACE, "WMI Access Failure, Error #: " + CStr(Err.Number) + ", Description: " + Err.Description
ScriptError "connect to WMI name space '\root\default'." &amp; GetErrorString(Err)
Else
IsWMIAccessible = True
End If

End Function


'******************************************************************************
' Name: CheckHealth
'
' Purpose: Checks the health of the Management Point. If the health state
' has changed, the new state is reported.
'
' Parameters: None
'
' Returns: Nothing
'
Sub CheckHealth

Dim intCurrentHealthState
Dim intPreviousHealthState

Dim strVersion


On Error Resume Next


'Get the current health state. Health State is only available in
'SMS 2003 SP1 builds beginning with build 3067.
'================================================================

strVersion = GetSMSVersion()

If StrComp(strVersion, "2.50.3067.0000", 1) &lt; 0 Then
g_oUtil.LogMessage g_oUtil.DBG_TRACE, "Monitoring Management Point health is not supported on this SMS build."
Exit Sub
End If

intCurrentHealthState = GetHealthState()

If IsEmpty(intCurrentHealthState) Then
Exit Sub
End If

g_oUtil.LogMessage g_oUtil.DBG_TRACE, "Current Management Point Health State = " &amp; intCurrentHealthState

'Get the previous saved health state.
'====================================

intPreviousHealthState = GetPreviousHealthState()

'If there was no previous health state or if the health state has
'changed, save the current state and submit an event for the new state.
'======================================================================

If IsEmpty(intPreviousHealthState) Or (intPreviousHealthState &lt;&gt; intCurrentHealthState) Then
CreateHealthStateEvent intCurrentHealthState
SetPreviousHealthState intCurrentHealthState
End If

If 0 &lt;&gt; Err.number Then
ScriptError "check Management Point health." &amp; GetErrorString(Err)
End If

End Sub


'******************************************************************************
' Name: GetHealthState
'
' Purpose: Get the current Management Point Health State from the registry.
'
' Parameters: None
'
' Returns: String, returns 0 if the Management Point is healthy otherwise 1.
' An empty string is returned if the value could not be found or
' accessed.
'
' Remarks: If an error is encountered this function will throw an exception
' the caller MUST handle this.
'
Function GetHealthState()

On Error Resume Next

GetHealthState = g_oUtil.ReadRegistryDWORDValue(g_oUtil.HKEY_LOCAL_MACHINE, g_oUtil.REG_KEY_SMS_SERVER_MANAGEMENT_POINT, g_oUtil.REG_VALUE_SMS_SERVER_MP_HEALTH_STATE)

End Function


'******************************************************************************
' Name: GetPreviousHealthState
'
' Purpose: Retrieves previously saved health state value out of a varset.
'
' Parameters: None
'
' Returns: Integer, the data to return or zero
'
Function GetPreviousHealthState()

Dim objScriptState
Dim objVarSet


On Error Resume Next


Set objScriptState = ScriptContext.GetScriptState()
Set objVarSet = objScriptState.GetSet(VARSET_NAME)

GetPreviousHealthState = objVarSet.get(VARSET_VAR_HEALTH_STATE)
'LogEvent EVENT_ID_NOTANEVENT, EVENT_TYPE_INFORMATION, "found previous Management Point Health State = " &amp; GetPreviousHealthState

Set objVarSet = Nothing
Set objScriptState = Nothing

End Function


'******************************************************************************
' Name: SetPreviousHealthState
'
' Purpose: Saves the specified health state value in a varset. If the key
' exists then the data associated with that key is replaced,
' otherwise the key/data combination is added to the varset.
'
' Parameters: intData, the health state value to save
'
' Returns: Nothing
'
Sub SetPreviousHealthState(intData)

Dim objScriptState
Dim objVarSet


On Error Resume Next


'Get the Management Point Health varset. If it does not exist,
'create it.
'==============================================================

Set objScriptState = ScriptContext.GetScriptState()
Set objVarSet = objScriptState.GetSet(VARSET_NAME)

If IsEmpty(objVarSet) Then
objVarSet = objScriptState.CreateSet()
End If

'Set, the health state.
'======================

objVarSet.put VARSET_VAR_HEALTH_STATE, intData

objScriptState.SaveSet VARSET_NAME, objVarSet

Set objVarSet = Nothing
Set objScriptState = Nothing

End Sub


'******************************************************************************
' Name: GetSMSVersion
'
' Purpose: Get the SMS Version from the registry.
'
' Parameters: None
'
' Returns: String, version if successful otherwise empty.
'
Function GetSMSVersion()

Dim strVersion


On Error Resume Next

Err.Clear

strVersion = g_oUtil.ReadRegistryStringValue(g_oUtil.HKEY_LOCAL_MACHINE, g_oUtil.REG_KEY_SMS_SERVER_OPERATIONS_MANAGEMENT, g_oUtil.REG_VALUE_SMS_SERVER_VERSION)

If IsEmpty(strVersion) Then
strVersion = g_oUtil.ReadRegistryStringValue(g_oUtil.HKEY_LOCAL_MACHINE, g_oUtil.REG_KEY_SMS_SERVER_SETUP, g_oUtil.REG_VALUE_SMS_SERVER_FULL_VERSION)
End If

GetSMSVersion = strVersion

End Function


'******************************************************************************
' Name: GetSMSSiteCode
'
' Purpose: Get the SMS Site Code from the registry.
'
' Parameters: None
'
' Returns: String, returns the SMS Site Code if successful otherwise empty.
'
' Remarks: If an error is encountered this function will throw an exception
' the caller MUST handle this.
'
Function GetSMSSiteCode()

Dim strSiteCode


On Error Resume Next

Err.Clear

strSiteCode = g_oUtil.ReadRegistryStringValue(g_oUtil.HKEY_LOCAL_MACHINE, g_oUtil.REG_KEY_SMS_SERVER_OPERATIONS_MANAGEMENT, g_oUtil.REG_VALUE_SMS_SERVER_SITE_CODE)

If IsEmpty(strSiteCode) Then
strSiteCode = g_oUtil.ReadRegistryStringValue(g_oUtil.HKEY_LOCAL_MACHINE, g_oUtil.REG_KEY_SMS_SERVER_IDENTIFICATION, g_oUtil.REG_VALUE_SMS_SERVER_SITE_CODE)
End If

GetSMSSiteCode = strSiteCode

End Function


'******************************************************************************
' Name: CreateHealthStateEvent
'
' Purpose: To generate a MOM event with a parameter containing the health
' state of the Management Point.
'
' Parameters: HealthState, the current health state
'
' Returns: Nothing
'
Sub CreateHealthStateEvent(intHealthState)

Dim oEvent

Dim strSiteCode
Dim strMessage


On Error Resume Next


'Create MOM event object.
'========================

Set oEvent = ScriptContext.CreateEvent

'Initialize the event object.
'============================

oEvent.EventType = EVENT_TYPE_INFORMATION
oEvent.EventNumber = EVENT_ID_MANAGEMENT_POINT_HEALTH

strSiteCode = GetSMSSiteCode()
oEvent.Category = strSiteCode

oEvent.SetEventParameter(intHealthState) ' Parameter1

strMessage = EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE &amp; strSiteCode

If intHealthState = 0 Then
strMessage = strMessage &amp; EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE_HEALTHY
Else
strMessage = strMessage &amp; EVENT_MSG_MANAGEMENT_POINT_HEALTH_STATE_UNHEALTHY
End If

oEvent.Message = strMessage

g_oUtil.LogMessage g_oUtil.DBG_TRACE, strMessage
g_oUtil.LogMessage g_oUtil.DBG_TRACE, "Submitting event " &amp; EVENT_ID_MANAGEMENT_POINT_HEALTH &amp; _
" with Health State = " &amp; intHealthState &amp; "."

'Submit, raise, this event to MOM.
'=================================

ScriptContext.Submit oEvent

'Cleanup
'=======

Set oEvent = Nothing

End Sub


'******************************************************************************
' Name: GetErrorString
'
' Purpose: Attempts to find the description for an error if an error with
' no description is passed in.
'
' Parameters: oErr, the error object
'
' Returns: String, the description for the error. (Includes the error code.)
'
Function GetErrorString(oErr)

Dim lErr, strErr


lErr = oErr
strErr = oErr.Description

On Error Resume Next

If 0 &gt;= Len(strErr) Then

' If we don't have an error description, then check to see if the error
' is a 0x8007xxxx error. If it is, then look it up.
Const ErrorMask = &amp;HFFFF0000
Const HiWord8007 = &amp;H80070000
Const LoWordMask = 65535 ' This is equivalent to 0x0000FFFF

If (lErr And ErrorMask) = HiWord8007 Then

' Attempt to use 'net helpmsg' to get a description for the error.
Dim oShell
Set oShell = CreateObject("WScript.Shell")

If Err = 0 Then

Dim oExec
Set oExec = oShell.Exec("net helpmsg " &amp; (lErr And LoWordMask))

Dim strMessage, i

Do
strMessage = oExec.stdout.ReadLine()
i = i + 1
Loop While (Len(strMessage) = 0) And (i &lt; 5)

strErr = strMessage

End If

End If

End If

GetErrorString = vbCrLf &amp; "The error returned was: '" &amp; strErr &amp; "' " &amp; lErr &amp; " (0x" &amp; Hex(lErr) &amp; ")"

End Function


'******************************************************************************
' Name: ScriptError
'
' Purpose: To generate a warning about a runtime script error.
'
' Parameters: strError, the description of the error
'
' Returns: Nothing
'
Sub ScriptError(strError)

LogEvent EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, "encountered a runtime error." &amp; vbCrLf &amp; "Failed to " &amp; strError

End Sub


'******************************************************************************
' Name: LogEvent
'
' Purpose: To generate a MOM event
'
' Parameters: lEventID, the event code
' lEventType, the severity of the event
' strMessage, the message to include in the event
'
' Returns: Nothing
'
Sub LogEvent(lEventID, lEventType, strMessage)

Dim objEvent


On Error Resume Next

Set objEvent = ScriptContext.CreateEvent

objEvent.EventNumber = lEventID
objEvent.EventType = lEventType
objEvent.Message = "The script '" &amp; ScriptContext.Name &amp; "' " &amp; strMessage

ScriptContext.Submit objEvent

End Sub


'==========================================================================
' Class: Util
' Description: Wrapper around WMI.
'==========================================================================
Class Util
'---------------
' Constants (Initialized on constructor due to VBS behavior)
'---------------
' Used to indicate to LogMessage when/how to print the message.
Public DBG_NONE
Public DBG_ERROR
Public DBG_WARNING
Public DBG_TRACE

'Internal Debug Level
Private m_nDebugLevel

'Registry root constants
Public HKEY_CLASSES_ROOT
Public HKEY_CURRENT_USER
Public HKEY_LOCAL_MACHINE
Public HKEY_USERS
Public HKEY_CURRENT_CONFIG
Public HKEY_DYN_CONFIG

'Registry path and key name constants
Public REG_PATH_SMS
Public REG_PATH_SMS_BASE

Public REG_PATH_SMS_CLIENT

Public REG_PATH_SMS_SERVER
Public REG_KEY_SMS_SERVER_IDENTIFICATION
Public REG_KEY_SMS_SERVER_OPERATIONS_MANAGEMENT
Public REG_KEY_SMS_SERVER_SETUP
Public REG_KEY_SMS_SERVER_MANAGEMENT_POINT

'Registry key value name constants
Public REG_VALUE_SMS_CLIENT_VERSION
Public REG_VALUE_SMS_CLIENT_SITE_CODE

Public REG_VALUE_SMS_SERVER_VERSION
Public REG_VALUE_SMS_SERVER_FULL_VERSION
Public REG_VALUE_SMS_SERVER_SITE_CODE

Public REG_VALUE_SMS_SERVER_MP_HEALTH_STATE

'---------------
' Methods
'---------------

'=============
' 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

HKEY_CLASSES_ROOT = &amp;H80000000
HKEY_CURRENT_USER = &amp;H80000001
HKEY_LOCAL_MACHINE = &amp;H80000002
HKEY_USERS = &amp;H80000003
HKEY_CURRENT_CONFIG = &amp;H80000005
HKEY_DYN_CONFIG = &amp;H80000006

'Registry path and key name constants
REG_PATH_SMS = "SOFTWARE\Microsoft\SMS"
REG_PATH_SMS_BASE = REG_PATH_SMS + "\"

REG_PATH_SMS_CLIENT = REG_PATH_SMS_BASE + "Mobile Client"

REG_PATH_SMS_SERVER = REG_PATH_SMS
REG_KEY_SMS_SERVER_IDENTIFICATION = REG_PATH_SMS_BASE + "Identification"
REG_KEY_SMS_SERVER_OPERATIONS_MANAGEMENT = REG_PATH_SMS_BASE + "Operations Management"
REG_KEY_SMS_SERVER_SETUP = REG_PATH_SMS_BASE + "Setup"
REG_KEY_SMS_SERVER_MANAGEMENT_POINT = REG_PATH_SMS_BASE + "MP"

'Registry key value name constants
REG_VALUE_SMS_CLIENT_VERSION = "ProductVersion"
REG_VALUE_SMS_CLIENT_SITE_CODE = "AssignedSiteCode"

REG_VALUE_SMS_SERVER_VERSION = "Version"
REG_VALUE_SMS_SERVER_FULL_VERSION = "Full Version"
REG_VALUE_SMS_SERVER_SITE_CODE = "Site Code"
REG_VALUE_SMS_SERVER_MP_HEALTH_STATE = "MPHealthState"

End Sub

'=============
' Method: Class_Terminate
' Description: This is the destructor
' Parameters:
'=============
Private Sub Class_Terminate()
End Sub

'=============
' Method: SetDebugLevel
' Description: To change the debugging output level of information
' generated by this utility.
' Parameters:
' nLevel - Level, either 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 &lt;= m_nDebugLevel) Then
If (nLevel = DBG_ERROR) Then
ScriptContext.Echo "[Error]: " + strMessage
ElseIf (nLevel = DBG_WARNING) Then
ScriptContext.Echo "[Warning]: " + strMessage
ElseIf (nLevel = DBG_TRACE) Then
ScriptContext.Echo "[Trace]:" + strMessage
End If
End If

End Sub

'=============
' Method: ReadRegistryStringValue
' Description: Used to read strings from the registry
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to read
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' strValueName - Name of the registry value to read (like "SoftwareType")
'
' Returns:
' The value of the registry key specified. "Nothing" if it fails.
' Callee needs to handle null value return.
'=============
Public Function ReadRegistryStringValue(ByVal lHive, ByVal strKeyPath, ByVal strValueName)

Dim oReg
Dim strValueData

'Get registry provider object
Call LogMessage(DBG_TRACE, "Connecting to WMI Registry : " + "winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")
Set oReg = WMIGetObject("winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")

'Read from value from registry
if oReg.GetStringValue(lHive, strKeyPath, strValueName, strValueData) = 0 Then
Call LogMessage(DBG_TRACE, "Value of Registry Key: " + strKeyPath + "\" + strValueName + " = " + strValueData)
ReadRegistryStringValue = strValueData
Else
Call LogMessage(DBG_ERROR, "Reading Registry Key: " + strKeyPath + "\" + strValueName + " Failed!" )
ReadRegistryStringValue = Empty
End If

Set oReg = Nothing

End Function

'=============
' Method: ReadRegistryDWORDValue
' Description: Used to read DWORDs from the registry
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to read
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' strValueName - Name of the registry value to read (like "SoftwareType")
'
' Returns:
' The value of the registry key specified. "Nothing" if it fails.
' Callee needs to handle null value return.
'=============
Public Function ReadRegistryDWORDValue(ByVal lHive, ByVal strKeyPath, ByVal strValueName)

Dim oReg
Dim lValueData

'Get registry provider object
Call LogMessage(DBG_TRACE, "Connecting to WMI Registry : " + "winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")
Set oReg = WMIGetObject("winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")

'Read value from registry
if oReg.GetDWORDValue(lHive, strKeyPath, strValueName, lValueData) = 0 Then
Call LogMessage(DBG_TRACE, "Value of Registry Key: " + strKeyPath + "\" + strValueName + " = " &amp; lValueData)
ReadRegistryDWORDValue = lValueData
Else
Call LogMessage(DBG_ERROR, "Reading Registry Key: " + strKeyPath + "\" + strValueName + " Failed!" )
ReadRegistryDWORDValue = Empty
End If

Set oReg = Nothing

End Function

'=============
' Method: EnumRegistryKeys
' Description: Used to enumerate registry keys under a given path
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to read
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' Returns:
' The list of registry keys found under the path. "null" if the list is empty
'=============
Public Function EnumRegistryKeys(ByVal lHive, ByVal strKeyPath)

Dim oReg
Dim arrKeys

'Get registry provider object
Call LogMessage(DBG_TRACE, "Connecting to WMI Registry : " + "winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")
Set oReg = WMIGetObject("winmgmts:\\"+ ScriptContext.TargetComputer + "\root\default:StdRegProv")

'Enumerate keys in registry
if oReg.EnumKey(lHive, strKeyPath, arrKeys) = 0 Then
Call LogMessage(DBG_TRACE, "Found [" + arrKeys(0) + "] key in path : " + strKeyPath )
EnumRegistryKeys = arrKeys
Else
Call LogMessage(DBG_ERROR, "Error enumerating Registry Keys under path : " + strKeyPath )
End If

Set oReg = Nothing

End Function

'=============
' Method: CheckRegistryKeyAccess
' Description: Used to check permissions access to a registry key
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to check access
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' lAccess - required permissions i.e. KEY_QUERY_VALUE + KEY_SET_VALUE
' Returns:
' True if the specified permissions are present on the registry key else false.
'=============
Public Function CheckRegistryKeyAccess(ByVal lHive, ByVal strKeyPath, ByVal lAccess)

Dim oReg
Dim bGranted

'Get registry provider object
Call LogMessage(DBG_TRACE, "Connecting to WMI Registry : " + "winmgmts:\\"+ ScriptContext.TargetComputer+ "\root\default:StdRegProv")
Set oReg = WMIGetObject("winmgmts:\\"+ ScriptContext.TargetComputer + "\root\default:StdRegProv")

'Check access to the specified registry key
if oReg.CheckAccess(lHive, strKeyPath, lAccess, bGranted) = 0 Then
Call LogMessage(DBG_TRACE, "Required access present on registry key : " + strKeyPath )
CheckRegistryKeyAccess = bGranted
Else
Call LogMessage(DBG_ERROR, "Error checking access on registry keys : " + strKeyPath )
CheckRegistryKeyAccess = False
End If

Set oReg = Nothing

End Function

'=============
' Method: CheckRegistryKeyExists
' Description: Used to check existence of a registry key
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to check access
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' Returns:
' True if the registry key exists else false.
'=============
Public Function CheckRegistryKeyExists(ByVal lHive, ByVal strKeyPath)

CheckRegistryKeyExists = CheckRegistryKeyAccess(lHive, strKeyPath, KEY_QUERY_VALUE)

End Function

'=============
' Method: CheckRegistryKeyStringValueExists
' Description: Used to check existence of a registry key string value
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to check access
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' Returns:
' True if the string value exists else false.
'=============
Public Function CheckRegistryKeyStringValueExists(ByVal lHive, ByVal strKeyPath, ByVal strValueName)

Dim strValue

strValue = ReadRegistryStringValue(lHive, strKeyPath, strValueName)

If IsEmpty(strValue) Then
CheckRegistryKeyStringValueExists = False
Else
CheckRegistryKeyStringValueExists = True
End If

End Function

'=============
' Method: CheckRegistryKeyDWORDValueExists
' Description: Used to check existence of a registry key DWORD value
' Parameters:
' lHive - Registry hive or root i.e. HKEY_LOCAL_MACHINE
' strKeyPath - Key path for the Registry key to check access
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' Returns:
' True if the DWORD value exists else false.
'=============
Public Function CheckRegistryKeyDWORDValueExists(ByVal lHive, ByVal strKeyPath, ByVal strValueName)

Dim lValue

lValue = ReadRegistryDWORDValue(lHive, strKeyPath, strValueName)

If IsEmpty(lValue) Then
CheckRegistryKeyDWORDValueExists = False
Else
CheckRegistryKeyDWORDValueExists = True
End If

End Function

End Class

'=============
' Method: WMIGetObject
' Description: Returns an object of type SWbemObjectSet
' Parameters:
' sNamespace - A WMI Namespace (ex. winmgmts:\\COMPUTERNAME\ROOT\cimv2).
'=============
Function WMIGetObject(sNamespace)
Dim oWMI
Dim nErrNumber, sErrDescription

On Error Resume Next
Set oWMI = GetObject(sNamespace)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If IsEmpty(oWMI) Or nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "Unable to open WMI Namespace " &amp; sNamespace
Err.Raise 9100, GET_WMI_NO_NAMESPACE_SOURCE(sNamespace), GET_WMI_NO_NAMESPACE_DESCRIPTION(nErrNumber, sErrDescription)
End If

Set WMIGetObject = oWMI

Set oWMI = Nothing
End Function

'=============
' Method: WMIGetInstance
' Description: Returns an object of type SWbemObjectSet
' Parameters:
' sNamespace - A WMI Namespace (ex. winmgmts:\\COMPUTERNAME\ROOT\cimv2).
' sInstance - A WMI Namespace Instance (ex. Win32_OperatingSystem)
'=============
Function WMIGetInstance(sNamespace, sInstance)
Dim oWMI, oInstance
Dim nErrNumber, sErrDescription

On Error Resume Next
Set oWMI = GetObject(sNamespace)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If IsEmpty(oWMI) Or nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "Unable to open WMI Namespace " &amp; sNamespace
Err.Raise 9100, GET_WMI_NO_NAMESPACE_SOURCE(sNamespace), GET_WMI_NO_NAMESPACE_DESCRIPTION(nErrNumber, sErrDescription)
End If

On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If IsEmpty(oInstance) Or nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "The class name '" &amp; sInstance &amp; "' returned no instances. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, GET_WMI_NO_INSTANCES_SOURCE(sInstance), GET_WMI_NO_INSTANCES_DESCRIPTION(nErrNumber, sErrDescription)
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
Dim nInstanceCount
nInstanceCount = oInstance.Count
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "The class name '" &amp; sInstance &amp; "' did not return any valid instances. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, GET_WMI_NO_VALID_INSTANCES_SOURCE(sInstance), GET_WMI_NO_VALID_INSTANCES_DESCRIPTION(nErrNumber, sErrDescription)
End If

Set WMIGetInstance = oInstance

Set oInstance = Nothing
Set oWMI = Nothing
End Function

'=============
' Method: WMIExecQuery
' Description: Returns an object of type SWbemObjectSet
' Parameters:
' sNamespace - A WMI Namespace (ex. winmgmts:\\COMPUTERNAME\ROOT\cimv2).
' sQuery - A SQL Query (ex. SELECT * FROM Win32_OperatingSystem)
'=============
Function WMIExecQuery(sNamespace, sQuery)
Dim oWMI, oQuery
Dim nErrNumber, sErrDescription

On Error Resume Next
Set oWMI = GetObject(sNamespace)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0

If IsEmpty(oWMI) Or nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "Unable to open WMI Namespace " &amp; sNamespace
Err.Raise 9100, GET_WMI_NO_NAMESPACE_SOURCE(sNamespace), GET_WMI_NO_NAMESPACE_DESCRIPTION(nErrNumber, sErrDescription)
End If

On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If IsEmpty(oQuery) Or nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "The Query '" &amp; sQuery &amp; "' returned an invalid result set. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, GET_WMI_QUERY_NO_RESULTS_SOURCE(sQuery), GET_WMI_QUERY_NO_RESULTS_DESCRIPTION(nErrNumber, sErrDescription)
End If

'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
Dim nInstanceCount
nInstanceCount = oQuery.Count
nErrNumber = Err.Number
sErrDescription = Err.Description
On Error Goto 0
If nErrNumber &lt;&gt; 0 Then
ScriptContext.Echo "The Query '" &amp; sQuery &amp; "' did not return any valid instances. Error:" &amp; nErrNumber &amp; ", " &amp; sErrDescription &amp; "."
Err.Raise 9100, GET_WMI_QUERY_NO_VALID_INSTANCES_SOURCE(sQuery), GET_WMI_QUERY_NO_VALID_INSTANCES_DESCRIPTION(nErrNumber, sErrDescription)
End If

Set WMIExecQuery = oQuery

Set oQuery = Nothing
Set oWMI = Nothing

End Function
</Script></Body>
<Language>VBScript</Language>
<Name>SMS 2003 Monitor Management Point Health</Name>
<Parameters/>
<ManagementPackId>[Microsoft.SMS.2003,,1.0.0.1]</ManagementPackId>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="RunScriptAction"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>SystemLibrary!System.BaseData</InputType>
</WriteActionModuleType>