Skip to main content

process and memory monitoring in mom 2005 [revisited]…

awhile back, a long while back, as it turns out, i wrote a couple of scripts that you could inject as responses in mom 2005 to generate a list of top cpu or memory processes.  here are the links to the old posts, in case you’ve forgotten about it.

mom: monitoring cpu spikes the right way
mom: memory processes

anyway, i realized today while daydreaming in between meetings and outage summaries, that i could write the information directly to the alert stream.  it’s so simple i could kick myself.

all i needed was one additional line.  now look at this… this is the old way i did it.

sMessage = "The processes using greater than " & Z & "k of memory are:" & VbCrLf & VbCrLf
For i = 0 To x - 1
    If aProcess(0,i) > z Then
        sMessage = sMessage & aProcess(1,i) & " : " & aProcess(0,i) & VbCrLf
     End If
Next
sMessage = sMessage & VbCrLf & "(There are " & x & " processes running at this time.)"

CreateEvent 40150,EVENT_TYPE_INFORMATION,"Memory Processes Script",sMessage

basically, you’d run this as a response script to a condition that was occurring.  you’d have to look at both alerts to see what was going on.  however, i found that since it’s executing as a response, it’s a part of the overall alert.  i’m sure someone had already written about that… but it just now made sense. 

here it is revised:

Set oAlert = ScriptContext.Alert

...

sMessage = "The processes using greater than " & Z & "k of memory are:" & VbCrLf & VbCrLf
For i = 0 To x - 1
    If aProcess(0,i) > z Then
        sMessage = sMessage & aProcess(1,i) & " : " & aProcess(0,i) & VbCrLf
     End If
Next
sMessage = sMessage & VbCrLf & "(There are " & x & " processes running at this time.)"

oAlert.Description = oAlert.Description & VbCrLf & VbCrLf & "[Top Memory Processes]" & VbCrLf & sMessage

as you can see, i had to create the object for scriptcontext.  instead of using the createevent function, i just write the alert object’s description with my additional information i’ve captured.  :)  instead of the standard, crappy information i get back from a mom performance counter, i now get back something that looks a little more polished…

Memory: Available MBytes: value = 276

[Top Memory Processes]
The processes using greater than 14681k of memory are:

myAntiVirus.exe : 119680
mySearch.exe : 284836
myPretendTestApp.exe : 16680
myApp1.exe : 53008
myApp2.exe : 28356
MOMService.exe : 17124

(There are 43 processes running at this time.)

 

 

i’ll post the links for the new scripts soon.  in the mean time, here are the scripts, if you want to pull them off the site:

TOP MEMORY:

'==========================================================================
'NAME        : Display Memory Processes
'AUTHOR        : Marcus C. Oh
'DATE        : 7/2/2008
'COMMENT        : Run as a response script to a rule that checks CPU utilization
'            : Lists processes utilizing % value of CPU over threshold
'            : Updated to write the memory information into the alert stream
'==========================================================================
Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4
Const EVENT_TYPE_AUDITSUCCESS = 8
Const EVENT_TYPE_AUDITFAILURE = 16

Set oAlert = ScriptContext.Alert
Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & ScriptContext.TargetNetbiosComputer & "\root\cimv2")
Set oProcesses = oWMIService.ExecQuery("SELECT * FROM Win32_Process")

Dim aProcess()

x = 0
For Each oProcess In oProcesses
    ReDim Preserve aProcess(2,x)    ' ReDim can only update the last dimension
    aProcess(0,x) = oProcess.WorkingSetSize / 1024
    aProcess(1,x) = oProcess.Name
    x = x + 1
Next

y = 0
For j = 0 To x - 1
     y = y + aProcess(0,j)    ' Count up the total memory used
Next

z = Round(y/x)                ' Divide total memory used by total processed and round it up

sMessage = "The processes using greater than " & Z & "k of memory are:" & VbCrLf & VbCrLf
For i = 0 To x - 1
    If aProcess(0,i) > z Then
        sMessage = sMessage & aProcess(1,i) & " : " & aProcess(0,i) & VbCrLf
     End If
Next
sMessage = sMessage & VbCrLf & "(There are " & x & " processes running at this time.)"

oAlert.Description = oAlert.Description & VbCrLf & VbCrLf & "[Top Memory Processes]" & VbCrLf & sMessage

Sub CreateEvent(iEventNumber,iEventType,sEventSource,sEventMessage)
    Set oEvent = ScriptContext.CreateEvent()
    oEvent.EventNumber = iEventNumber
    oEvent.EventType = iEventType 
    oEvent.EventSource = sEventSource
    oEvent.Message = sEventMessage
    ScriptContext.Submit oEvent
End Sub

 

TOP CPU:

'=============================================================================
'NAME        : TopProcesses Script
'AUTHOR        : Marcus C. Oh
'DATE        : 7/2/2008
'COMMENT        : Run as a response script to a rule that checks CPU utilization
'            : Bastardized from Microsoft Windows Base OS CPU Overload Script
'            : Lists processes utilizing % value of CPU over threshold
'            : Modified to post to Alert stream
'=============================================================================
Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4
Const EVENT_TYPE_AUDITSUCCESS = 8
Const EVENT_TYPE_AUDITFAILURE = 16

Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & ScriptContext.TargetNetbiosComputer & "\root\cimv2")
Set oAlert = ScriptContext.Alert
 
lNumProcessors = GetNumProcessors()
iPercentage = ScriptContext.Parameters.Get("Percentage")
sMessage = ListCriticalProcesses(iPercentage,lNumProcessors)
oAlert.Description = oAlert.Description & VbCrLf & VbCrLf & "[Top CPU Processes]" & VbCrLf & sMessage

Sub CreateEvent(iEventNumber,iEventType,sEventSource,sEventMessage)
    Set oEvent = ScriptContext.CreateEvent()
    oEvent.EventNumber = iEventNumber
    oEvent.EventType = iEventType 
    oEvent.EventSource = sEventSource
    oEvent.Message = sEventMessage
    ScriptContext.Submit oEvent
End Sub

Function WMIGetObject(ByVal sNamespace)
    Dim oWMI
    Dim e
    Set e = New Error
    On Error Resume Next
    Set oWMI = GetObject(sNamespace)
    e.Save
    On Error Goto 0
    If IsEmpty(oWMI) Then
        ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'.  Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
    End If
    Set WMIGetObject = oWMI
End Function

Function GetNumProcessors()
    Dim oReg, sValue
    Const HKEY_LOCAL_MACHINE = &h80000002
    Const REGPATH_NUMBER_OF_CPUS = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment\"
    Const REGKEY_NUMBER_OF_CPUS = "NUMBER_OF_PROCESSORS"
    Set oReg = WMIGetObject("winmgmts://" & ScriptContext.TargetNetbiosComputer & "/root/default:StdRegProv")
    oReg.GetStringValue HKEY_LOCAL_MACHINE, REGPATH_NUMBER_OF_CPUS, REGKEY_NUMBER_OF_CPUS, sValue
    GetNumProcessors = sValue
End Function

Function ListCriticalProcesses(Percentage,lNumProcessors)
    On Error Resume Next
    Dim oDictionary, oProcesses, oProcess
    Set oDictionary = CreateObject("Scripting.Dictionary")
    Set oProcesses = oWMIService.ExecQuery("SELECT * FROM Win32_PerfRawData_PerfProc_Process")
    For Each oProcess in oProcesses
        oDictionary.Item(oProcess.Name & oProcess.IDProcess & "%") = oProcess.PercentProcessorTime
        oDictionary.Item(oProcess.Name & oProcess.IDProcess & "#") = oProcess.Timestamp_Sys100NS
    Next
    Set oProcesses = Nothing

    ScriptContext.Sleep(500)

    Dim sProcesses, lNumProcesses
    Set oProcesses = oWMIService.ExecQuery("SELECT * FROM Win32_PerfRawData_PerfProc_Process")

    For Each oProcess In oProcesses
        lNumProcesses = lNumProcesses + 1
        Dim fPercentProcessor
        If oDictionary.Exists(oProcess.Name & oProcess.IDProcess & "%") Then
            fPercentProcessor = (oProcess.PercentProcessorTime - CDbl(oDictionary.Item(oProcess.Name & oProcess.IDProcess & "%"))) / _ 
            (oProcess.Timestamp_Sys100NS - CDbl(oDictionary.Item(oProcess.Name & oProcess.IDProcess & "#"))) * 100
            If (fPercentProcessor > (Percentage * lNumProcessors)) And (oProcess.IDProcess <> 0) Then
                sProcesses = sProcesses & oProcess.Name & " (" & oProcess.IDProcess & ") :" & _
                CInt(fPercentProcessor / lNumProcessors) & "%" & VbCrLf
            End If
        End If
    Next
    Set oProcesses = Nothing

    If Len(sProcesses) > 0 Then
        ListCriticalProcesses = "The processes using greater than " & Percentage & "% CPU at present are:" & vbCrLf & _
                                sProcesses & VbCrLf & _
                                "(There are " & lNumProcesses & " running at this time.)"
    End If
    Set oDictionary = Nothing
End Function

Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
    Dim sErrDescription, sErrNumber
    sErrDescription = oErr.Description
    sErrNumber = oErr.Number
    On Error Resume Next
    Dim oScriptErrorEvent
    Set oScriptErrorEvent = ScriptContext.CreateEvent()
    With oScriptErrorEvent
        .EventNumber = 40000
        .EventType = EVENT_TYPE_ERROR
        .Message = sMessage
        .SetEventParameter """Top Processes"""
        .SetEventParameter sMessage
        .SetEventParameter sErrDescription
        .SetEventParameter sErrNumber
    End With
    ScriptContext.Submit oScriptErrorEvent
    ScriptContext.Echo "ThrowScriptError('" & sMessage & "')"
End Function

Class Error
    Private m_lNumber
    Private m_sSource
    Private m_sDescription
    Private m_sHelpContext
    Private m_sHelpFile
    Public Sub Save()
        m_lNumber = Err.number
        m_sSource = Err.Source
        m_sDescription = Err.Description
        m_sHelpContext = Err.HelpContext
        m_sHelpFile = Err.helpfile
    End Sub
    Public Sub Raise()
        Err.Raise m_lNumber, m_sSource, m_sDescription, m_sHelpFile, m_sHelpContext
    End Sub
    Public Sub Clear()
        m_lNumber = 0
        m_sSource = ""
        m_sDescription = ""
        m_sHelpContext = ""
        m_sHelpFile = ""
    End Sub
    Public Default Property Get Number()
        Number = m_lNumber
    End Property
    Public Property Get Source()
        Source = m_sSource
    End Property
    Public Property Get Description()
        Description = m_sDescription
    End Property
    Public Property Get HelpContext()
        HelpContext = m_sHelpContext
    End Property
    Public Property Get HelpFile()
        HelpFile = m_sHelpFile
    End Property    
End Class

Comments

  1. I just came across your blog, this is exactly the type of stuff I need for our MoM 2005 env. Thank you, I'll be testing these script in dev before pushing to prod but I have a feeling they rock!

    ReplyDelete
  2. Excellent script, I will be using this. Who knew someone was still writing great stuff for MoM 2005. I think your blog is a goldmine.

    ReplyDelete
  3. glad you like it man. hope you find it works well for you...

    ReplyDelete
  4. the new TOP CPU script is causing the following error:
    An error occurred on line 18 while executing script 'Top Processes'
    Source: Microsoft VBScript runtime error
    Description: Class doesn't support Automation

    ReplyDelete
  5. maybe there's a line incorrect in your script. email your copy over to me. i'll have a look.

    ReplyDelete

Post a Comment

Popular posts from this blog

using preloadpkgonsite.exe to stage compressed copies to child site distribution points

UPDATE: john marcum sent me a kind email to let me know about a problem he ran into with preloadpkgonsite.exe in the new SCCM Toolkit V2 where under certain conditions, packages will not uncompress.  if you are using the v2 toolkit, PLEASE read this blog post before proceeding.   here’s a scenario that came up on the mssms@lists.myitforum.com mailing list. when confronted with a situation of large packages and wan links, it’s generally best to get the data to the other location without going over the wire. in this case, 75gb. :/ the “how” you get the files there is really not the most important thing to worry about. once they’re there and moved to the appropriate location, preloadpkgonsite.exe is required to install the compressed source files. once done, a status message goes back to the parent server which should stop the upstream server from copying the package source files over the wan to the child site. anyway, if it’s a relatively small amount of packages, you can

How to Identify Applications Using Your Domain Controller

Problem Everyone has been through it. We've all had to retire or replace a domain controller at some point in our checkered collective experiences. While AD provides very intelligent high availability, some applications are just plain dumb. They do not observe site awareness or participate in locating a domain controller. All they want is the name or IP of one domain controller which gets hardcoded in a configuration file somewhere, deeply embedded in some file folder or setting that you are never going to find. How do you look at a DC and decide which applications might be doing it? Packet trace? Logs? Shut it down and wait for screaming? It seems very tedious and nearly impossible. Potential Solution Obviously I wouldn't even bother posting this if I hadn't run across something interesting. :) I ran across something in draftcalled Domain Controller Isolation. Since it's in draft, I don't know that it's published yet. HOWEVER, the concept is based off

sccm: content hash fails to match

back in 2008, I wrote up a little thing about how distribution manager fails to send a package to a distribution point . even though a lot of what I wrote that for was the failure of packages to get delivered to child sites, the result was pretty much the same. when the client tries to run the advertisement with an old package, the result was a failure because of content mismatch. I went through an ordeal recently capturing these exact kinds of failures and corrected quite a number of problems with these packages. the resulting blog post is my effort to capture how these problems were resolved. if nothing else, it's a basic checklist of things you can use.   DETECTION status messages take a look at your status messages. this has to be the easiest way to determine where these problems exist. unfortunately, it requires that a client is already experiencing problems. there are client logs you can examine as well such as cas, but I wasn't even sure I was going to have enough m