Tray icon now displays the current CPU usage, and the tooltip is almost exactly the same as Process Explorer's (current CPU usage + process using most of the CPU)

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@433 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2008-12-27 06:52:14 +00:00
parent 41eb3baece
commit 03130abd9c
9 changed files with 180 additions and 40 deletions
+3
View File
@@ -10,6 +10,9 @@ Process Hacker
techniques
* NEW: Highlighting for UAC elevated processes
* NEW: Struct reader (with support for user-defined structs)
* NEW: Tray icon now displays the current CPU usage, and the tooltip is almost
exactly the same as Process Explorer's (current CPU usage + process using most
of the CPU)
* FIXED: Shows SIDs without names in SDDL format
* FIXED: Less "Access denied" errors - uses PROCESS_QUERY_LIMITED_INFORMATION
on Vista
@@ -71,6 +71,17 @@ namespace ProcessHacker
get { return _pitem.Name; }
}
public string DisplayPID
{
get
{
if (_pitem.PID >= 0)
return _pitem.PID.ToString();
else
return "";
}
}
public int PID
{
get { return _pitem.PID; }
@@ -88,7 +99,13 @@ namespace ProcessHacker
public string CPU
{
get { return _pitem.CPUUsage.ToString("F2"); }
get
{
if (_pitem.CPUUsage == 0)
return "";
else
return _pitem.CPUUsage.ToString("F2");
}
}
private string GetBestUsername(string username, bool includeDomain)
@@ -135,7 +135,7 @@
//
// nodePID
//
this.nodePID.DataPropertyName = "PID";
this.nodePID.DataPropertyName = "DisplayPID";
this.nodePID.EditEnabled = false;
this.nodePID.IncrementalSearchEnabled = true;
this.nodePID.LeftMargin = 3;
+47 -24
View File
@@ -48,6 +48,8 @@ namespace ProcessHacker
ProcessSystemProvider processP = new ProcessSystemProvider();
ServiceProvider serviceP = new ServiceProvider();
UsageIcon cpuUsageIcon = new UsageIcon(16, 16);
Dictionary<int, List<string>> processServices = new Dictionary<int, List<string>>();
int processSelectedItems;
@@ -756,6 +758,22 @@ namespace ProcessHacker
#region Providers
private void processP_Updated()
{
processP.DictionaryAdded += new ProcessSystemProvider.ProviderDictionaryAdded(processP_DictionaryAdded);
processP.DictionaryRemoved += new ProcessSystemProvider.ProviderDictionaryRemoved(processP_DictionaryRemoved);
processP.Updated -= new ProcessSystemProvider.ProviderUpdateOnce(processP_Updated);
if (processP.RunCount >= 1)
this.Invoke(new MethodInvoker(UpdateCommon));
}
private void processP_IconUpdater()
{
cpuUsageIcon.Update(processP.CurrentCPUUsage);
notifyIcon.Icon = cpuUsageIcon.GetIcon();
}
public void processP_DictionaryAdded(ProcessItem item)
{
ProcessItem parent = new ProcessItem();
@@ -794,6 +812,20 @@ namespace ProcessHacker
"The process " + item.Name + " (" + item.PID.ToString() + ") was terminated.", ToolTipIcon.Info);
}
private void serviceP_Updated()
{
listServices.List.EndUpdate();
HighlightedListViewItem.StateHighlighting = true;
serviceP.DictionaryAdded += new ServiceProvider.ProviderDictionaryAdded(serviceP_DictionaryAdded);
serviceP.DictionaryModified += new ServiceProvider.ProviderDictionaryModified(serviceP_DictionaryModified);
serviceP.DictionaryRemoved += new ServiceProvider.ProviderDictionaryRemoved(serviceP_DictionaryRemoved);
serviceP.Updated -= new ServiceProvider.ProviderUpdateOnce(serviceP_Updated);
if (processP.RunCount >= 1)
this.Invoke(new MethodInvoker(UpdateCommon));
}
public void serviceP_DictionaryAdded(ServiceItem item)
{
this.QueueMessage("New Service: " + item.Status.ServiceName +
@@ -1151,6 +1183,17 @@ namespace ProcessHacker
private void timerFire_Tick(object sender, EventArgs e)
{
UpdateStatusInfo();
notifyIcon.Text = "Process Hacker\n" +
"CPU Usage: " + (processP.CurrentCPUUsage * 100).ToString("F2") + "%";
try
{
notifyIcon.Text += "\n" + processP.Dictionary[processP.PIDWithMostCPUUsage].Name +
": " + processP.Dictionary[processP.PIDWithMostCPUUsage].CPUUsage.ToString("F2") + "%";
}
catch
{ }
}
private void timerMessages_Tick(object sender, EventArgs e)
@@ -1383,30 +1426,6 @@ namespace ProcessHacker
((MenuItem)sender).Checked = !((MenuItem)sender).Checked;
}
private void serviceP_Updated()
{
listServices.List.EndUpdate();
HighlightedListViewItem.StateHighlighting = true;
serviceP.DictionaryAdded += new ServiceProvider.ProviderDictionaryAdded(serviceP_DictionaryAdded);
serviceP.DictionaryModified += new ServiceProvider.ProviderDictionaryModified(serviceP_DictionaryModified);
serviceP.DictionaryRemoved += new ServiceProvider.ProviderDictionaryRemoved(serviceP_DictionaryRemoved);
serviceP.Updated -= new ServiceProvider.ProviderUpdateOnce(serviceP_Updated);
if (processP.RunCount >= 1)
this.Invoke(new MethodInvoker(UpdateCommon));
}
private void processP_Updated()
{
processP.DictionaryAdded += new ProcessSystemProvider.ProviderDictionaryAdded(processP_DictionaryAdded);
processP.DictionaryRemoved += new ProcessSystemProvider.ProviderDictionaryRemoved(processP_DictionaryRemoved);
processP.Updated -= new ProcessSystemProvider.ProviderUpdateOnce(processP_Updated);
if (processP.RunCount >= 1)
this.Invoke(new MethodInvoker(UpdateCommon));
}
private void UpdateCommon()
{
timerMessages.Enabled = true;
@@ -1441,8 +1460,12 @@ namespace ProcessHacker
processP.Interval = RefreshInterval;
treeProcesses.Provider = processP;
processP.Updated += new ProcessSystemProvider.ProviderUpdateOnce(processP_Updated);
processP.Updated += new Provider<int, ProcessItem>.ProviderUpdateOnce(processP_IconUpdater);
processP.Enabled = true;
cpuUsageIcon.BackColor = Color.Black;
cpuUsageIcon.Color = Color.Red;
HighlightedListViewItem.HighlightingDuration = Properties.Settings.Default.HighlightingDuration;
HighlightedListViewItem.StateHighlighting = false;
listServices.List.BeginUpdate();
+1
View File
@@ -194,6 +194,7 @@
this.checkShowTrayIcon.TabIndex = 7;
this.checkShowTrayIcon.Text = "Show tray icon";
this.checkShowTrayIcon.UseVisualStyleBackColor = true;
this.checkShowTrayIcon.CheckedChanged += new System.EventHandler(this.checkShowTrayIcon_CheckedChanged);
//
// tabHighlighting
//
@@ -98,5 +98,18 @@ namespace ProcessHacker
Program.HackerWindow.ProcessList.RefreshItems();
this.Close();
}
private void checkShowTrayIcon_CheckedChanged(object sender, EventArgs e)
{
if (checkShowTrayIcon.Checked)
{
checkHideWhenMinimized.Enabled = true;
}
else
{
checkHideWhenMinimized.Enabled = false;
checkHideWhenMinimized.Checked = false;
}
}
}
}
+39 -4
View File
@@ -19,7 +19,8 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Reflection;
using System.Text;
@@ -32,17 +33,51 @@ namespace ProcessHacker
public class UsageIcon
{
private List<float> _values;
private int _width;
private int _height;
public UsageIcon(int size)
public UsageIcon(int width, int height)
{
_values = new List<float>(size);
_values = new List<float>();
_width = width;
_height = height;
for (int i = 0; i < width; i++)
_values.Add(0);
}
public void Update(float value)
{
if (value > 1)
throw new ArgumentOutOfRangeException();
// shift values left, push value onto the end
_values.RemoveAt(0);
_values.Add(value);
}
public Color BackColor { get; set; }
public Color Color { get; set; }
public Icon GetIcon()
{
using (Bitmap bm = new Bitmap(_width, _height))
{
using (Graphics g = Graphics.FromImage(bm))
{
g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 0, _width, _height));
for (int x = 0; x < _width; x++)
{
int height = (int)(_values[x] * _height);
g.DrawLine(new Pen(this.Color), new Point(x, _height), new Point(x, _height - height));
}
return Icon.FromHandle(bm.GetHicon());
}
}
}
}
}
@@ -56,6 +56,7 @@ namespace ProcessHacker
public class ProcessSystemProvider : Provider<int, ProcessItem>
{
private long _lastIdleTime;
private long _lastSysTime;
public ProcessSystemProvider()
@@ -69,23 +70,53 @@ namespace ProcessHacker
Win32.ZwQuerySystemInformation(Win32.SYSTEM_INFORMATION_CLASS.SystemBasicInformation, ref basic,
Marshal.SizeOf(basic), out retLen);
this.System = basic;
this.ProcessorPerfArray = new Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[this.System.NumberOfProcessors];
this.UpdateProcessorPerf();
_lastSysTime = this.ProcessorPerf.KernelTime + this.ProcessorPerf.UserTime;
_lastIdleTime = this.ProcessorPerf.IdleTime;
}
public Win32.SYSTEM_BASIC_INFORMATION System { get; private set; }
public Win32.SYSTEM_PERFORMANCE_INFORMATION Performance { get; private set; }
public Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorPerf { get; private set; }
public Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] ProcessorPerfArray { get; private set; }
public float CurrentCPUUsage { get; private set; }
public int PIDWithMostCPUUsage { get; private set; }
private void UpdateProcessorPerf()
{
int retLen;
Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION procPerf = new Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION();
using (MemoryAlloc data =
new MemoryAlloc(Marshal.SizeOf(typeof(Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) *
this.ProcessorPerfArray.Length))
{
int retLen;
Win32.ZwQuerySystemInformation(Win32.SYSTEM_INFORMATION_CLASS.SystemProcessorTimes,
ref procPerf, Marshal.SizeOf(procPerf), out retLen);
this.ProcessorPerf = procPerf;
Win32.ZwQuerySystemInformation(Win32.SYSTEM_INFORMATION_CLASS.SystemProcessorTimes,
data, data.Size, out retLen);
var newAverages = new Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION();
for (int i = 0; i < this.ProcessorPerfArray.Length; i++)
{
this.ProcessorPerfArray[i] = data.ReadStruct<Win32.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION>(
i);
newAverages.DpcTime += this.ProcessorPerfArray[i].DpcTime
/ this.ProcessorPerfArray.Length;
newAverages.IdleTime += this.ProcessorPerfArray[i].IdleTime
/ this.ProcessorPerfArray.Length;
newAverages.InterruptCount += this.ProcessorPerfArray[i].InterruptCount
/ this.ProcessorPerfArray.Length;
newAverages.InterruptTime += this.ProcessorPerfArray[i].InterruptTime
/ this.ProcessorPerfArray.Length;
newAverages.KernelTime += this.ProcessorPerfArray[i].KernelTime
/ this.ProcessorPerfArray.Length;
newAverages.UserTime += this.ProcessorPerfArray[i].UserTime
/ this.ProcessorPerfArray.Length;
}
this.ProcessorPerf = newAverages;
}
}
private void UpdatePerformance()
@@ -113,12 +144,17 @@ namespace ProcessHacker
_lastSysTime = thisSysTime;
long thisIdleTime = this.ProcessorPerf.IdleTime;
long idleTime = thisIdleTime - _lastIdleTime;
_lastIdleTime = thisIdleTime;
// set System Idle Process CPU time
if (procs.ContainsKey(0))
{
Win32.SystemProcess proc = procs[0];
proc.Process.KernelTime = this.ProcessorPerf.IdleTime * 4; // must not be divided by 4
proc.Process.KernelTime = this.ProcessorPerf.IdleTime * this.System.NumberOfProcessors;
procs.Remove(0);
procs.Add(0, proc);
}
@@ -130,7 +166,7 @@ namespace ProcessHacker
{
ProcessId = -2,
InheritedFromProcessId = 0,
KernelTime = this.ProcessorPerf.DpcTime * 4,
KernelTime = this.ProcessorPerf.DpcTime * this.System.NumberOfProcessors,
SessionId = -1
}
});
@@ -142,11 +178,13 @@ namespace ProcessHacker
{
ProcessId = -3,
InheritedFromProcessId = 0,
KernelTime = this.ProcessorPerf.InterruptTime * 4,
KernelTime = this.ProcessorPerf.InterruptTime * this.System.NumberOfProcessors,
SessionId = -1
}
});
float mostCPUUsage = 0;
// look for dead processes
foreach (int pid in Dictionary.Keys)
{
@@ -306,8 +344,14 @@ namespace ProcessHacker
try
{
newitem.CPUUsage = ((float)(newitem.LastTime - item.LastTime) * 100 / sysTime) /
newitem.CPUUsage = (float)(newitem.LastTime - item.LastTime) * 100 / sysTime /
this.System.NumberOfProcessors;
if (pid != 0 && newitem.CPUUsage > mostCPUUsage)
{
mostCPUUsage = newitem.CPUUsage;
this.PIDWithMostCPUUsage = pid;
}
}
catch
{ }
@@ -349,6 +393,9 @@ namespace ProcessHacker
}
}
if (thisSysTime != 0)
this.CurrentCPUUsage = (float)(sysTime - idleTime) / (sysTime);
Dictionary = newdictionary;
wtsEnumData.Memory.Dispose();
+2 -1
View File
@@ -610,7 +610,8 @@ namespace ProcessHacker
[DllImport("ntdll.dll", SetLastError = true)]
public static extern uint ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,
ref SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemInformation, int SystemInformationLength, out int ReturnLength);
[MarshalAs(UnmanagedType.LPArray)] SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] SystemInformation,
int SystemInformationLength, out int ReturnLength);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern uint ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,