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:
static void Main()
{
PerformanceDetector.Instance.initialize();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
PerformanceDetector.Instance.destroy();
}
Add:
PerformanceDetector.Instance.initialize();
before Application.Run
.
Add:
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.
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.
Like this, it only shows the memory usage.
When I used it I found I could not do anything when it showed.
This is my second idea, I
decided using a single form wouldl be better:
And I also added CPU usage on the form.
Techniques
I use
PerformanceCounter
to monitor the usage of CPU in
the current process.
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.
[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.
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.
Process currentProcess = Process.GetCurrentProcess();
currentProcess.WorkingSet64;
And we use Process.Modules
and
ProcessModule.ModuleMemorySize
to get detail information.
ProcessModuleCollection myProcessModuleCollection = currentProcess.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;
}
}
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