Introduction
Following is an application for those who want to know, what is the COM+ application name behind a specific process ID (i.e. dllhost.exe process) and for those who want to monitor memory used by these COM+ components.
Background
There are two ways that COM+ can host .NET components: Library applications and Server applications. A library application runs the component in the caller process while a server application runs the component in a dedicate process that COM+ creates, called Dllhost.exe. Server application runs in a separate process affecting the overall performance of the application that needs to cross the process boundary to call component services.
Many organizations and individuals want to monitor their COM+ applications, like what is the COM+ application name behind a process ID and how much memory is being used by a COM+ component. This inspired me to make a simple application that possess the above features mentioned.
Using the code
The first step is to add reference to the following namespaces:
using System;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Forms;
using COMSVCSLib;
using System.Runtime.InteropServices;
Whenever you press "Get Application(s)" button, inside the btnGetApplications_Click(object sender, System.EventArgs e)
function, the GetCOMPlusApplicationsList();
function is called. This is the main function that gets the list of all running COM+ applications and also gets the associated process ID.
public GetCOMPlusApplicationsList()
{
COMSVCSLib.MtsGrp GrpObj = null;
Type dcomType = Type.GetTypeFromProgID("mts.MtsGrp");
Object dcomObj = Activator.CreateInstance( dcomType );
GrpObj = (COMSVCSLib.MtsGrp) dcomObj;
object obj = null;
COMSVCSLib.COMEvents eventObj = null;
for (int i = 0 ;i < GrpObj.Count ; ++i)
{
GrpObj.Item (i, out obj);
eventObj = (COMSVCSLib.COMEvents) obj;
AddtoListView(eventObj.GetProcessID(),eventObj.PackageName);
Marshal.ReleaseComObject(obj);
obj = null;
Marshal.ReleaseComObject(eventObj);
eventObj = null;
}
Marshal.ReleaseComObject( dcomObj );
dcomObj = null;
return;
}
In GetCOMPlusApplicationsList()
function, first of all, it creates a reference object of interface COMSVCSLib.MtsGrp
which is used to enumerate through the running packages. Later you need to get the type associated with the specified program identifier (progID). In this case, "mts.MtsGrp
" progID is specified to get the type associated with this component. The next step is to create an instance of this type object by calling the .NET class function Activator.CreateInstance( dcomType )
.
Now you get the MtsGrp
object. You can get each instance by using the GrpObj.Item (i, out obj)
function, and type cast it to COMEvents
object like this:
eventObj = (COMSVCSLib.COMEvents) obj;
Next step is calling the function eventObj.GetProcessID()
and eventObj.PackageName
function and properties respectively to get the process ID and application name of the running COM+ application. After that AddtoListView
function is called which adds the process ID and application name to the ListView
. After that you need to call the Marshal.ReleaseComObject(obj)
function defined in the System.Runtime.InteropServices.Marshal
to release the memory resources held by this object. See what is happening in AddtoListView
function:
private void AddtoListView(int pid, string appName)
{
listItem = this.comlistView.Items.Add(pid.ToString());
listItem.SubItems.Add(appName);
}
When you get the COM+ applications, then you can get the memory used by these COM+ applications. For this, you can select the COM+ application you want to know about and after that press "Get Memory" button which in response shows you the memory usage in terms of bytes. Now let's see what happens in the Click
event of the "Get Memory" button.
private void getMemoryButton_Click(object sender, System.EventArgs e)
{
string pid = this.pidTextBox.Text ;
if(pid =="")
{
MessageBox.Show("Please enter a process Id!", "Process ID");
return;
}
Process []getProcess = Process.GetProcesses();
foreach(Process pro in getProcess)
{
if(pro.Id.ToString() == pid)
{
this.phyMemTextBox.Text = pro.WorkingSet.ToString() + " bytes";
this.virTextBox.Text = pro.VirtualMemorySize.ToString() + " bytes";
return;
}
}
MessageBox.Show("Invalid process Id","Invalid ID");
}
Points of Interest
This was the first assignment given to me in my software house Ultimus. First I tried hard to get the running COM+ packages, but later when I explored a lot, this solution stuck into my mind and I finally came with this idea. Before that I never got familiar with COM+ components. But this application could be very useful for those organizations which usually use COM+ packages.
History
- 28 July 2005: Initial release.