Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Comonitor - A COM+ Monitor

0.00/5 (No votes)
7 Dec 2005 1  
A COM+ monitoring application.

Introduction

This article provides system administrators with a tool to monitor COM+ applications (Remote and Local) the managed way.

Background

As a system administrator, I use the COM+ MMC on a daily basis looking for deadlocked or un-disposed components. After crawling the web for quite some time, I managed to find a small piece of C# code which helped me build this monitoring application. (The code was found in Egil Hogholt's blog, the C# version was added as a comment by Mark.)

Comonitor Architecture

The core of the application is the "COMSVCSLib.TrackerServer" object which returns info only for the local server. To overcome this problem, I decided to wrap the core code (using the TrackerServer object) in a WebService which will be installed on each of my servers. My client application uses SOAP to call the web service on a remote server (the remote server name is given as a parameter at runtime).

Understanding the ComonitorService

The ComonitorService has only one WebMethod ("GetErrors") which gets two uint parameters from the client:

  • "ResponseTimeLimit" - uint representing the response time (m\s) which the client considers as a deadlock.
  • "ObjectsLimit" - uint representing the number of un-disposed components which the client considers as an error.
[WebMethod]
[XmlInclude(typeof(Comonitor.OverLimitObject))]
public ArrayList GetErrors(uint ResponseTimeLimit, 
                                uint ObjectsLimit)

"GetErrors" returns an ArrayList of ComonitorService.OverLimitObjects with all the problematic components.

public class OverLimitObject
{
    public string  PackageName;
    public string  ComponentName;
    public uint    PID;     
    public uint    ResponseTime;
    public uint    Objects;
}

"OverLimitObject" contains all the necessary information received from the "COMSVCSLib.TrackerServer" object.

Using the "COMSVCSLib.TrackerServer"

The following code is the core of the Comonitor application. It uses the "COMSVCSLib.TrackerServer" object to query the COM Catalog for (only) the running components. For each component which corresponds to the given limit parameters, we create a "ComonitorService.OverLimitObject" containing the relevant data from the component's statistics.

ArrayList retVal = new ArrayList();
IntPtr clsIDDataPtr    = IntPtr.Zero;
IntPtr appDataPtr    = IntPtr.Zero;
COMSVCSLib.IGetAppData getAppData = null;

// Get an instance of the internal com+ tracker objet

COMSVCSLib.TrackerServer comPlusTrackerType;
comPlusTrackerType = new COMSVCSLib.TrackerServerClass();
getAppData = (COMSVCSLib.IGetAppData)comPlusTrackerType;

// Get a list of running application

uint appCount;
unsafe 
{ 
    getAppData.GetApps(out appCount, new IntPtr(&appDataPtr)); 
}

// Step through the list of running application

int appDataSize = Marshal.SizeOf(typeof(COMSVCSLib.appData)); 
for(int appIndex=0; appIndex<appCount; appIndex++) 
{
    COMSVCSLib.appData appData = 
               (COMSVCSLib.appData)Marshal.PtrToStructure(new 
               IntPtr(appDataPtr.ToInt32() + (appIndex * appDataSize)), 
               typeof(COMSVCSLib.appData));
    
    // Get information about running application

    uint nClsIDCount;
    appDataPtr = new IntPtr();
    unsafe
    {
        getAppData.GetAppData(appData.m_idApp, out nClsIDCount, 
                                    new IntPtr(&clsIDDataPtr)); 
    }
    
    // Step through the information

    int clsIDDataSize = Marshal.SizeOf(typeof(COMSVCSLib.CLSIDDATA));
    for(int clsIDIndex=0; clsIDIndex<nClsIDCount; clsIDIndex++) 
    {
        COMSVCSLib.CLSIDDATA clsIDData = 
           (COMSVCSLib.CLSIDDATA)Marshal.PtrToStructure(new 
           IntPtr(clsIDDataPtr.ToInt32() + (clsIDIndex * clsIDDataSize)), 
           typeof(COMSVCSLib.CLSIDDATA));
        
        // Checks if any parameter is over the limit

        // (which was provided by the user)

        if ((clsIDData.m_cBound >= ObjectsLimit) || 
            (clsIDData.m_dwRespTime >= ResponseTimeLimit))
        {
            //Creates Over Limit Objects and adds it to retVal

            OverLimitObject objOL = new 
               OverLimitObject(GetPackageNameByPID(appData.m_dwAppProcessId), 
               GetComponentNameByCLSID(clsIDData.m_clsid.ToString()), 
               appData.m_dwAppProcessId, clsIDData.m_dwRespTime, 
               clsIDData.m_cBound);
            retVal.Add(objOL);
        }
    }
}
return retVal;

The Client

In this article, I also included a Windows client application which uses the "ComonitorService". The example client application calls the WebService on a specified computer every given time period (optional) and provides the sys admin with the capability to shut down a problematic package on the specified server. If there are COM+ packages which you don't want to be checked, such as: system application, IIS utilities etc., you can add the package names into the client's App.config inside the "NonErrorPackages" key.

<add key="NonErrorPackages" value="System Application,IIS Utilities" />

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here