Wednesday, November 30, 2011

[SCOM 2007] Authoring Management Pack - Create a VBS discovery with a debugging functionnality - PART I

For this first article, I'll show you how to create a discovery in VBS that implement a debugging functionnality. We all have already created a MP with a discovery or a script that is working when it's launched manualy and not working when SCOM executed it. For example property bags not set or targeted servers not discovered...
The idea is to create a registry key dedicated to the developped MP on the targeted servers with the discovery at the first time it's launched. The key could set to TRUE or FALSE and be placed in HKLM\SOFTWARE\Microsoft\Microsoft Operations Manager\Debugging and called Verbose.MyNewMP.
Reading the value of this key will give us the 'debugging mode' for the MP on a specific targeted server. We will also store the value in a property of the discovered class in the MP to be able to re-used the property in all the Monitors and rules that target the class.
 Here is some function we will need to create the discovery :

Create or edit a registry key in VBS

  1. Private Function fct_WriteRegistryKey(ByVal strKeyPath, ByVal strKeyName, ByVal strKeyValue)
  2. ' Write a Registry value to strKeyPath\strKeyName with value strKeyValue
  3. ' blnKeyEdit is set to True or false in case of error.
  4.             Dim blnKeyEdit
  5.             Dim oWshShell
  6.             blnKeyEdit = false
  7.             'Try to set strKeyValue to the registry key strKeyPath\strKeyName
  8.             On Error Resume Next
  9.             Set oWshShell = WScript.CreateObject("WScript.Shell")
  10.             oWshShell.RegWrite strKeyPath & "\" & strKeyName , UCase(strKeyValue)
  11.             'If setting the registry key strKeyValue is OK Then the function will return a string TRUE.
  12.             If err.number = 0 Then
  13.                         blnKeyEdit = true
  14.             End if
  15.             On error goto 0
  16.             fct_WriteRegistryKey = blnKeyEdit
  17. End Function

Used to Create or edit Registry key strKeyPath\strKeyName with value given by strKeyValue strKeyPath & strKeyName should be set as :
- strKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\Debugging"
- strKeyName = "Verbose.MyNewMP"
- strKeyValue should be TRUE or FALSE

The function returns a boolean set to true if the Registry modification is successful or false if it failed

Reading a registry key in VBS

  
  1. Private Function fct_ReadRegistryKey(ByVal strKeyPath, ByVal strKeyName)
  2. 'Read Registry key located on KeyPath\KeyName
  3. 'Returns the value of a registry key and eventually a no-value to identify that the key does not exists.
  4.            Dim oWshShell
  5.             Dim strRegReadValue     'Contains the value of the Registry Key
  6.             'Try to read the registry key located to strKeyPath\strKeyName
  7.             On Error Resume Next
  8.             Set oWshShell = CreateObject("Wscript.Shell")
  9.             strRegReadValue = oWshShell.RegRead(strKeyPath &"\" & strKeyName)
  10.             'If an error is raised Then we a no-value to identify that the Registry Key does not exist.
  11.             If err.number <> 0 Then
  12.                         strRegReadValue = ""
  13.             End if
  14.             On error goto 0
  15.             fct_ReadRegistryKey = UCase(strRegReadValue)
  16. End Function

Used to Read Registry key located on strKeyPath\strKeyName.
strKeyPath & strKeyName should be set as :
- strKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft OperationsManager\Debugging"
- strKeyName = "Verbose.MyNewMP"
The function returns eventually the value of strRegReadValue which contains the value of strKeyName.
strRegReadValue can be blank or set with a text value.


We will use the Operation Manager Event log to create some events that will help us to debug the differents scripts used in the MP. Do do it we need to create a function to create some events in the log.

 Write an event in the Operation Manager Event Log
  1. Private Sub sub_LogMPScriptEvent(ByVal intErrNumber, ByVal strEventLogMessage, ByRef objError, ByVal strDebugMod, ByVal strScriptName, ByVal strMomEventLevel)
  2. ' Log an event in the OperationManager eventLog of the server if it is in debug mode
  3. ' It will allow to trace the debugging process of the script of the Management Pack by logging errors and parameters values
  4.             Dim strMessage
  5.              strMessage=""
  6.              'If the debug mode is ON, an event is logged in the Operation Manager eventLog.
  7.             If ucase(strDebugMod) = "TRUE" Then
  8.                         strMessage = strEventLogMessage & vbCrLf & " " & vbCrLf & _
  9.                         "Error number:" & vbTab & CStr(objError.Number) & vbCrLf & _ 
  10.                         "Error description:" & vbTab & objError.Description
  11.             Call oAPI.LogScriptEvent(strScriptName, intErrNumber, strMomEventLevel, strMessage)
  12.             End if
  13. End Sub

Used to log an error event in the Operation Manager Event Log. Event number is given by intErrNumber, description by strEventLogMessage. strDebugMod must be equal to True for, if not, no event will be created.

Because of some right issue on some script I've already developped, I decided to add a function to create an event in the Operation Manager Event Log that will give the running account used by the script by using the sub_LogMPScriptEvent function.

Give running account in an event in the event log

  1. Private function fct_LogRunningAccount(ByVal strDebugMode)
  2. ' Log an event in the OperationManager eventLog of the server if it is in debug mode
  3. ' It allows to know under which credentials the script is executed
  4.             Dim owshNetwork
  5.             Dim strRunningUserID
  6.             On Error Resume Next
  7.             Set owshNetwork = WScript.CreateObject("WScript.Network")
  8.             'Assign user name returned to a variable
  9.             strRunningUserID = owshNetwork.UserName
  10.             
  11.             call sub_LogMPScriptEvent (4005, "sub_LogMPScriptEvent. Script running as user: " & strRunningUserID , Err, strDebugMode,strMPScriptName,MOMEVENTLOGINFORMATION)
  12.             On error goto 0
  13.             fct_LogRunningAccount = strRunningUserID
  14. End Function

 The last need I had was to create an event that contains :
  • The account used to run the script
  • The number of script parameters
  • The values of the parameters
  • The value of the debug mode
 Create event with all the default information used by the discovery script
  1. private sub sub_LogScriptStartInfo(byRef oArgs, byVal strDebugModeValue, byval strMomLevelEvent, byVal strScriptName)
  2. ' Log an event with the default informations. The event contains :
  3. ' - The account used to run the script
  4. ' - The number of script parameters
  5. ' - The values of the parameters
  6. ' - The value of the debug mode
  7.             Dim owshNetwork
  8.             Dim strLogMessage
  9.             Dim strRunAsAccount
  10.             On Error Resume Next
  11.             Set owshNetwork = WScript.CreateObject("WScript.Network")
  12.             'Assign user name returned to a variable
  13.             strRunAsAccount = owshNetwork.UserName
  14.              strLogMessage=""
  15.             ' Create the start log Script with launch information data RunAs account, debugmode, arguments)
  16.             strLogMessage = vbcrlf & "The script has been launched under following credentials : "            strRunAsAccount & "." & vbcrlf & vbcrlf & oArgs.count & " arguments have been passed in parameter : "
  17.             For intIndex = 0 To oArgs.Count-1
  18.                         strLogMessage = strLogMessage & vbcrlf & " - " & oArgs(intIndex)
  19.             Next
  20.             strLogMessage = strLogMessage & vbcrlf & vbcrlf & "The debug mode value for the Management Pack is set to : " & strDebugModeValue
  21.             Call oAPI.LogScriptEvent(strScriptName, 10212, strMomLevelEvent, strLogMessage)
  22. End sub


Be careful : to use these function you will have to create the object that connect to MOM API :
  1. ' Create the object that connect to MOM API
  2. Set oAPI = CreateObject("MOM.ScriptAPI")
But we will see that in the discovery script I'll expose in the PART II

 End of PART I
                                                                                                                     Go to Part II

This posting is provided "AS IS" with no warranties.