65.9K
CodeProject 正在变化。 阅读更多。
Home

Comonitor - COM+ 监视器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (7投票s)

2005年12月7日

2分钟阅读

viewsIcon

55170

downloadIcon

1376

一个 COM+ 监控应用程序。

引言

本文为系统管理员提供了一个以托管方式监控 COM+ 应用程序(远程和本地)的工具。

背景

作为一名系统管理员,我每天都会使用 COM+ MMC 来查找死锁或未释放的组件。 在网上搜索了很长时间后,我找到了一小段 C# 代码,帮助我构建了这个监控应用程序。(这段代码来自 Egil Hogholt 的博客,Mark 以评论的形式添加了 C# 版本。)

Comonitor 架构

该应用程序的核心是 "COMSVCSLib.TrackerServer" 对象,它仅返回本地服务器的信息。 为了克服这个问题,我决定将核心代码(使用 TrackerServer 对象)封装在一个 WebService 中,该 WebService 将安装在我的每个服务器上。 我的客户端应用程序使用 SOAP 调用远程服务器上的 WebService(远程服务器名称作为运行时参数提供)。

理解 ComonitorService

ComonitorService 只有一个 WebMethod ("GetErrors"),它从客户端获取两个 uint 参数

  • "ResponseTimeLimit" - uint,表示客户端认为死锁的响应时间(毫秒)。
  • "ObjectsLimit" - uint,表示客户端认为错误的未释放组件数量。
[WebMethod]
[XmlInclude(typeof(Comonitor.OverLimitObject))]
public ArrayList GetErrors(uint ResponseTimeLimit, 
                                uint ObjectsLimit)

"GetErrors" 返回一个包含所有有问题组件的 ComonitorService.OverLimitObjectArrayList

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

"OverLimitObject" 包含从 "COMSVCSLib.TrackerServer" 对象接收到的所有必要信息。

使用 "COMSVCSLib.TrackerServer"

以下代码是 Comonitor 应用程序的核心。 它使用 "COMSVCSLib.TrackerServer" 对象查询 COM 目录以获取(仅)正在运行的组件。 对于与给定限制参数对应的每个组件,我们创建一个 "ComonitorService.OverLimitObject",其中包含来自组件统计信息的相关数据。

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;

客户端

在本文中,我还包含了一个 Windows 客户端应用程序,它使用 "ComonitorService"。 示例客户端应用程序每隔给定的时间段(可选)调用指定计算机上的 WebService,并为系统管理员提供关闭指定服务器上存在问题的包的能力。 如果有您不想检查的 COM+ 包,例如:系统应用程序、IIS 实用程序等,您可以将包名称添加到客户端的 App.config 文件中的 "NonErrorPackages" 键中。

<add key="NonErrorPackages" value="System Application,IIS Utilities" />
© . All rights reserved.