If your computer is running hot or battery is running out quickly, then it is most likely due to some application or process consuming high CPU or memory. If you keep running applications for a long time, for example, Outlook, then it continues to grow in memory consumption and does not free up memory efficiently. As a result, your computer runs out of physical memory and other applications run slower. Sometimes Outlook, browser, image editing applications or some other applications start taking full CPU as they get into some infinite loop and make your CPU hot and you get sluggish performance from your application.
CPUAlert is an application that monitors CPU and memory consumption of applications and alerts you if some application is consistently taking high CPU or high memory. It will not only save your CPU and battery’s lifetime but also make your computer run smoothly and let your active applications run as fast as possible.
How to Use the Application
While it is running, if some process is consuming more than 200 MB memory, it will show you an alert:
Here you can see that my Outlook is taking 244 MB of physical RAM.
You can either postpone the alert for 5 mins (just press ESC), or ignore the process permanently so that you no longer receive alerts for the process anymore, or you can close it and reclaim memory.
The handy feature is “Restart” which closes the application and starts again. This generally frees up memory that clogs up the process.
The same alert will come up if some process is consuming more than 30% CPU for over 5 mins.
You can configure all these settings like what’s the tolerable limit for CPU and memory, how frequently to show the alert, how long to wait before closing an application, etc. by right clicking on the Task bar icon and choosing Settings.
The application registers itself to start at Windows startup. If you want to remove it from Windows Startup, just delete the application shortcut from Start Menu->All Programs->Startup menu.
Using the Code
CPU Alert is a small project. The important files are:
- MonitorCPUForm.cs: This is the main window which is loaded when the app starts. It hides itself in the system tray and keeps the app running in background. It also hosts a "Settings" view which lets you change the CPU and Memory threshold, alert interval, etc. It also orchestrates the operations and shows the necessary alerts.
- KillProcessForm.cs: It has just the UI for the alert that you see in the above popup. No intelligence.
- Monitor.cs: This is the important class that does the monitoring, measurement of CPU and Memory usage and raises the alert. If you want to have this kind of feature in your application, you can reuse this class.
Let's look at the Monitor.cs class first which has the brainpower to monitor CPU and memory. It uses WMI to monitor the processes. I tried using
Process class first and tried to access the
TotalProcessorTime but it gave me "Access Denied" for processes like
mysqld. For some processes, I did not get the
WorkingSet and so on. Then I tried using
PerformanceCounter to get the CPU and Memory usage of process. It was too expensive to query Performance Counter for each process. So, I had to rely on WMI to give me the information.
private ManagementObjectSearcher _Searcher =
"SELECT IDProcess, Name, PercentProcessorTime, Description,
WorkingSet FROM Win32_PerfFormattedData_PerfProc_Process");
private List<ProcessInfo> GetUsage()
var processes = new List<ProcessInfo>();
foreach (ManagementObject queryObj in _Searcher.Get())
var process = new ProcessInfo
Id = Convert.ToInt32(queryObj["IDProcess"]),
Name = Convert.ToString(queryObj["Name"]),
CpuUsage = Convert.ToInt32(queryObj["PercentProcessorTime"]),
Description = Convert.ToString(queryObj["Description"]),
WorkingSet = Convert.ToInt64(queryObj["WorkingSet"]),
process.Title = process.Name;
process.Title = process.Description;
if (process.Id > 0)
Pretty straight forward. The only cool thing to learn here is I declared the
ManageObjectSearcher as a
private variable, not a local variable to this function because it seems creating and disposing it every time the
GetUsage function is called is very expensive. CPU was getting 20% for about 30 seconds on
WMIpserv.exe whenever I tried to create and dispose the searcher.
Closing a process turned out to be a R&D challenge. You can kill a process by calling
Process.Kill, but that terminates the process abnormally. If you are killing Outlook this way, it causes data corruption. So, you have to gracefully close the application. However, if some app is stuck and taking 100% CPU, trying to close it gracefully does not work. You have to take drastic measures. In that case, killing it is only the solution.
So, first I try to close the process gently:
private void CloseProcess(ProcessInfo processToKill)
Process process = Process.GetProcessById(processToKill.Id);
processToKill.Path = process.MainModule.FileName;
catch (Exception closeException)
if (MessageBox.Show(this, "Unable to close process: "
+ (processToKill.Title) + Environment.NewLine
+ closeException.Message + Environment.NewLine
+ "Do you want to kill it?", "Unable to close process",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
Here it calls the
Process.CloseMainWindow function to send a shutdown message to the process. If the process has a visual window, it will receive the message and hopefully it will close itself soon. If there's no visual window, then it will not receive the message and it will not shutdown. So, we will have to kill it.
Even if some process receives the shutdown message, it may not terminate properly if it's stuck in some infinite loop. In that case, we need to check back after a while if it's still running and then kill it.
private void KillProcess(ProcessInfo processToKill)
foreach (Process process in Process.GetProcessesByName(processToKill.Name))
if (process.Id == processToKill.Id)
catch (Exception killException)
MessageBox.Show(this, "Unable to kill process: "
+ Environment.NewLine + "You should restart your computer",
"Unable to kill process",
This function is fired from a timer. We wait for a while and then go for the kill. First check, if the process is still lying around. If it is, then kill it.
Another interesting topic is memory usage. As you know, Windows Forms apps when started, take up about 10 MB to 15 MB memory. It's too much for a utility which is running in the background and trying to save you some memory. It's because when .NET WinForms libraries load, they load a lot of stuff hoping you would need it and it would save additional load time. So, I had to force .NET to flush out any unused stuff. I have a
MemoryHelper which does this:
static class MemoryHelper
static extern int EmptyWorkingSet(IntPtr hwProc);
public static void ClearMemory()
First it forces a Garbage Collection, then it calls the
EmptyWorkingSet function on
psapi.dll to flush out the working set, which is the physical memory allocation. I don't know whether or not it works, but at least Taskbar shows that the app now takes only 5 MB memory. Super!
CPUAlert will save you from slowing down your PC or burning out laptop batteries quickly. If you find it useful, please spread the love. Start by voting for this article.
- 2nd March, 2010: Initial post