Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#3.5

Easy Performance Monitor Plug-in

4.62/5 (7 votes)
12 Dec 2013CPOL2 min read 15.9K   273  
An easy to use plug-in to monitor CPU and memory usage.

Introduction

The article will explain my idea for this plug-in and what techniques I use.

Sometimes I need to monitor the usage of CPU and memory, but I don't like to always use the Windows Task Manager. I want to record some logs when the usage of memory is too large and generate some reports to use in meetings. I got an idea, maybe I can implement a tool, and it can bind in any project and show the information when I need. I think I could use some control keys to show it.

Using the code

It can be used in any Windows Forms project. After you create a new Windows Forms project, you must add a DLL reference and add this code in Program.cs:

C#
static void Main()
{
    PerformanceDetector.Instance.initialize();
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new frmMain());
    PerformanceDetector.Instance.destroy();
}

Add:

C#
PerformanceDetector.Instance.initialize(); 

before Application.Run.

Add:

C#
PerformanceDetector.Instance.destroy(); 

after Application.Run.

Press Alt+Ctrl+m, and it will show a small dialog to display the usage of CPU and memory.

Idea for the tool 

I hope I can show the monitor tool when I need, but I don't want to it to show using a menu, button, or other UI component. At last I decided to use some control keys.

Image 1

The first version of the plug-in was just a bind in user control. I developed some code to monitor the usage of memory and used Alt+Ctrl+M to show that on a Windows Form.

Image 2

Like this, it only shows the memory usage.

When I used it I found I could not do anything when it showed.

Image 3

This is my second idea, I decided using a single form wouldl be better:

Image 4

And I also added CPU usage on the form.

Techniques

I use PerformanceCounter to monitor the usage of CPU in the current process.

C#
theCPUCounter = new PerformanceCounter("Process", 
      "% Processor Time", Process.GetCurrentProcess().ProcessName);
m_cpuUsage = (int)(theCPUCounter.NextValue() / Environment.ProcessorCount);

public PerformanceCounter(
	string categoryName,
	string counterName,
	string instanceName )

I wanted to get the usage of CPU in the current process, so the first parameter must pass Process, second parameter is "% Processor Time" to get the usage of CPU, and the last parameter is the name of the current process that is got by Process.GetCurrentProcess().ProcessName.

Calling the NextValue() function will get the usage of CPU.

And I use Environment.ProcessorCount to calculate it.

C#
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern int SetWindowsHookEx(int idHook, _HookProcHandler lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();  

I use some hook APIs to handle the control keys. Why? Because I hope I can show the monitor at anytime, but I don't want to code it all in the form.

HookManager is an easy to use hook class.

C#
HookManager.Instance.RegisterHook(HookType.WH_KEYBOARD, 
          new CustomHookProc.HookProcHandler(KeyboardHookProc));

void KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    KeyStateInfo ctrlKey = KeyboardInfo.GetKeyState(Keys.ControlKey);
    KeyStateInfo altKey = KeyboardInfo.GetKeyState(Keys.Alt);
    KeyStateInfo mKey = KeyboardInfo.GetKeyState(Keys.M);
    if (ctrlKey.IsPressed && altKey.IsPressed && mKey.IsPressed)
    {
        showMonitorForm();
    }
}

It's easy to register an event and handle.

At last, I use Process.WorkingSet64 to get the usage of memory.

C#
Process currentProcess = Process.GetCurrentProcess();
currentProcess.WorkingSet64; 

And we use Process.Modules and ProcessModule.ModuleMemorySize to get detail information.

C#
ProcessModuleCollection myProcessModuleCollection = currentProcess.Modules;
// Display the 'ModuleMemorySize' of each of the modules.
ProcessModule myProcessModule;
for (int i = 0; i < myProcessModuleCollection.Count; i++)
{
    myProcessModule = myProcessModuleCollection[i];
    if (m_moduleMemorys.Keys.Contains(myProcessModule.ModuleName))
        m_moduleMemorys[myProcessModule.ModuleName].update(myProcessModule.ModuleMemorySize);
    else
    {
        MemoryInfo mem = new MemoryInfo();
        mem.Name = myProcessModule.ModuleName;
        mem.update(myProcessModule.ModuleMemorySize);
        m_moduleMemorys[myProcessModule.ModuleName] = mem;
    }
}

Image 5

C#
public class MemoryInfo
{
    string m_name;
    long m_currentUsage;
    long m_maximumUsage;
    public long MaximumUsage
    {
        get { return m_maximumUsage; }
        set { m_maximumUsage = value; }
    }
    public long CurrentUsage
    {
        get { return m_currentUsage; }
        set { m_currentUsage = value; }
    }
    public string Name
    {
        get { return m_name; }
        set { m_name = value; }
    }
    public string GetCurrentKB()
    {
        return Convert.ToString(m_currentUsage / 1024.0);
    }
    public string GetMaximumKB()
    {
        return Convert.ToString(m_maximumUsage / 1024.0);
    }
    public void update(long current)
    {
        m_currentUsage = current;
        if (m_currentUsage > m_maximumUsage)
            m_maximumUsage = m_currentUsage;
    }
}

It is just a simple class to store memory usage information.

  • Name: Stores ProcessModule.ModuleName.
  • CurrentUsage: Handles the usage of memory.
  • MaximumUsage: Handles the max usage of memory.

History

  • v1.0: First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)