SMS 2003 Service Discovery - Client

SMS_2003_Service_Discovery___Client (WriteActionModuleType)

Performs Service Discovery for SMS clients

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
InputTypeSystem.BaseData
Comment{F9180EE9-3C5A-42B7-94EB-48989998C218}

Member Modules:

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

Source Code:

<WriteActionModuleType ID="SMS_2003_Service_Discovery___Client" Accessibility="Internal" Comment="{F9180EE9-3C5A-42B7-94EB-48989998C218}">
<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 Service Discovery - Client
'
' Purpose - Performs service discovery functions on SMS 2003 Advanced
' Clients.
'
' Assumptions - This script will only run on SMS 2003 Advanced Clients.
'
' Parameters - None
'
' Change Hist - Date Version Description
' -------- --------------- -----------
' 02/10/04 02.50.0161.0000 Created
' 04/08/04 02.50.0174.0000 Update for new state monitoring
' component support.
' 07/01/04 05.0.2704.0000 Added support for IA64.
'
' (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


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

'Start Localization
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


'Discovery Constants
'===================

Const DISCOVERY_SCOPE_ID = "{030F2D6E-EAEA-4751-8DBA-9D324A0D139B}" 'Rule GUID or the PR that runs this script

Const COMPUTER_CLASS_ID = "Computer"
Const COMPUTER_COMPUTER_NAME_ATTRIBUTE_ID = "ComputerName"
Const COMPUTER_TIME_ZONE_BIAS_ATTRIBUTE_ID = "Time Zone Bias"
Const COMPUTER_OPERATING_SYSTEM_VERSION_ATTRIBUTE_ID = "Operating System Version"
Const COMPUTER_IP_ADDRESS_ATTRIBUTE_ID = "IPAddress"
Const COMPUTER_FQDN_ATTRIBUTE_ID = "FQDN"

Const SMS_CLIENT_CLASS_ID = "SMS Client"
Const SMS_CLIENT_NAME_ATTRIBUTE_ID = "Name"
Const SMS_CLIENT_VERSION_ATTRIBUTE_ID = "Version"
Const SMS_CLIENT_SITE_CODE_ATTRIBUTE_ID = "Site Code"
Const SMS_CLIENT_SERVICE_COMPONENT_ID = "Service"


'Other constants
'===============

Const SCRIPT_NAME = "SMS 2003 Service Discovery - Client"


' 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
'
' Remarks: This routine will manage its error return.
'
Sub Main()

On Error Resume Next

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

Set g_oUtil = new Util

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_TRACE)

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

'WMI is used by discovery functions in this script so check that it is
'accessible.
'=====================================================================

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

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

DoServiceDiscovery

Call g_oUtil.LogMessage(g_oUtil.DBG_TRACE, " " + SCRIPT_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.
'
' Remarks: If an error is encountered this function will throw an exception
' the caller MUST handle this.
'
Function IsWMIAccessible()

Dim objService


On Error Resume Next

Err.Clear


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

If Err Then
IsWMIAccessible = False
Call g_oUtil.LogMessage(g_oUtil.DBG_TRACE, "WMI Access Failure, Error #: " + CStr(Err.Number) + ", Description: " + Err.Description)
Else
IsWMIAccessible = True
End If

End Function

'******************************************************************************
' Name: DoServiceDiscovery
'
' Purpose: Performs all discovery service functions.
'
' Parameters: None
'
' Returns: Nothing
'
' Remarks: This routine will manage its error return.
'
Sub DoServiceDiscovery

Dim oDiscData

'Create Discovery Data object.
'=============================

Call g_oUtil.LogMessage(g_oUtil.DBG_TRACE, "Creating DiscoveryData packet." )

Set oDiscData = ScriptContext.CreateDiscoveryData()

oDiscData.ScopeID = DISCOVERY_SCOPE_ID

'Initialize Discovery Data object for the SMS class.
'===================================================

Initialize oDiscData

'Submit the Discovery Data object.
'=================================

Call g_oUtil.LogMessage(g_oUtil.DBG_TRACE, "Submitting Discovery data packet.")

ScriptContext.Submit oDiscData

End Sub

'******************************************************************************
' Name: Initialize
'
' Purpose: Initializes Discovery Data object for appropriate SMS class(es).
'
' Parameters: ByVal oDiscData Discovery Data oject returned by
' ScriptContext.CreateDiscoveryData().
'
' Returns: Nothing
'
' Remarks: This routine will manage its error return.
'
Sub Initialize(ByVal oDiscData)

Dim oCollection
Dim oInstance

Dim strClientVersion
Dim strClientSiteCode

'Initialize the discovery class components (subgroups or functions) and
'properties of the class.
'======================================================================

Set oCollection = oDiscData.CreateCollection()

With oCollection
.ClassID = SMS_CLIENT_CLASS_ID
.AddScopeFilter COMPUTER_COMPUTER_NAME_ATTRIBUTE_ID, ScriptContext.TargetComputerIdentity
.AddScopeComponent SMS_CLIENT_SERVICE_COMPONENT_ID
' .AddScopeProperty SMS_CLIENT_NAME_ATTRIBUTE_ID
.AddScopeProperty SMS_CLIENT_VERSION_ATTRIBUTE_ID
.AddScopeProperty SMS_CLIENT_SITE_CODE_ATTRIBUTE_ID
End With

Set oInstance = oCollection.CreateInstance()

strClientVersion = g_oUtil.ReadRegistryValue(g_oUtil.REG_PATH_SMS_CLIENT, g_oUtil.REG_VALUE_SMS_CLIENT_VERSION)

If IsEmpty(strClientVersion) Then
strClientVersion = g_oUtil.ReadRegistryValue(g_oUtil.REG_PATH_SMS_CLIENT_64BIT, g_oUtil.REG_VALUE_SMS_CLIENT_VERSION)
End If

strClientSiteCode = g_oUtil.ReadRegistryValue(g_oUtil.REG_PATH_SMS_CLIENT, g_oUtil.REG_VALUE_SMS_CLIENT_SITE_CODE)

If IsEmpty(strClientSiteCode) Then
strClientSiteCode = g_oUtil.ReadRegistryValue(g_oUtil.REG_PATH_SMS_CLIENT_64BIT, g_oUtil.REG_VALUE_SMS_CLIENT_SITE_CODE)
End If

With oInstance
.AddComponent SMS_CLIENT_SERVICE_COMPONENT_ID
.AddKeyProperty SMS_CLIENT_NAME_ATTRIBUTE_ID, ScriptContext.TargetNetbiosComputer
.AddProperty SMS_CLIENT_VERSION_ATTRIBUTE_ID, strClientVersion
.AddProperty SMS_CLIENT_SITE_CODE_ATTRIBUTE_ID, strClientSiteCode
End With

oCollection.AddInstance oInstance
oDiscData.AddCollection oCollection

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_64BIT

Public REG_PATH_SMS_BASE
Public REG_PATH_SMS_BASE_64BIT

Public REG_PATH_SMS_CLIENT
Public REG_PATH_SMS_CLIENT_64BIT

'Registry key value name constants
Public REG_VALUE_SMS_CLIENT_VERSION
Public REG_VALUE_SMS_CLIENT_SITE_CODE

'---------------
' 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_64BIT = "SOFTWARE\Wow6432Node\Microsoft\SMS"

REG_PATH_SMS_BASE = REG_PATH_SMS + "\"
REG_PATH_SMS_BASE_64BIT = REG_PATH_SMS_64BIT + "\"

REG_PATH_SMS_CLIENT = REG_PATH_SMS_BASE + "Mobile Client"
REG_PATH_SMS_CLIENT_64BIT = REG_PATH_SMS_BASE_64BIT + "Mobile Client"

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

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: ReadRegistryValue
' Description: Used to read strings from the registry
' Parameters:
' strKeyPath - Key path for the Registry key to read
' (like "SOFTWARE\Microsoft\WindowsNT\CurrentVersion")
' strValueName - Name of the registry entry 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 ReadRegistryValue(strKeyPath, strValueName)

Dim strValueData, oReg

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 registry
if oReg.GetStringValue(HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValueData) = 0 Then
Call LogMessage(DBG_TRACE, "Value of Registry Key: " + strKeyPath + "\" + strValueName + " = " + strValueData)
ReadRegistryValue = strValueData
Else
Call LogMessage(DBG_ERROR, "Reading Registry Key: " + strKeyPath + "\" + strValueName + " Failed!" )
ReadRegistryValue = empty
End If

Set oReg = Nothing

End Function

'=============
' Method: EnumRegistryKeys
' Description: Used to enumerate registry keys under a given path
' Parameters:
' 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 strKeyPath)

Dim arrKeys, oReg, HostName

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 registry
if oReg.EnumKey(HKEY_LOCAL_MACHINE, 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

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 Service Discovery - Client</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>