mirror of
https://github.com/ckaczor/ProcessCpuUsageStatusWindow.git
synced 2026-01-13 17:23:02 -05:00
Add implementation
This commit is contained in:
18
App.config
18
App.config
@@ -1,6 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="ProcessCpuUsageStatusWindow.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<ProcessCpuUsageStatusWindow.Properties.Settings>
|
||||
<setting name="ProcessCount" serializeAs="String">
|
||||
<value>3</value>
|
||||
</setting>
|
||||
<setting name="UpdateInterval" serializeAs="String">
|
||||
<value>00:00:02</value>
|
||||
</setting>
|
||||
<setting name="WindowSettings" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</ProcessCpuUsageStatusWindow.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
28
App.xaml.cs
28
App.xaml.cs
@@ -1,17 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
public partial class App
|
||||
{
|
||||
private WindowSource _windowSource;
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
base.OnStartup(e);
|
||||
|
||||
_windowSource = new WindowSource();
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
_windowSource.Dispose();
|
||||
|
||||
base.OnExit(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
ProcessCpuUsage.cs
Normal file
60
ProcessCpuUsage.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow
|
||||
{
|
||||
public class ProcessCpuUsage
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public string ProcessName { get; private set; }
|
||||
public float PercentUsage { get; internal set; }
|
||||
public DateTime LastFound { get; set; }
|
||||
public bool UsageValid { get; private set; }
|
||||
|
||||
internal CounterSample LastSample { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
internal ProcessCpuUsage(InstanceData instanceData)
|
||||
: this(instanceData, DateTime.MinValue)
|
||||
{ }
|
||||
|
||||
internal ProcessCpuUsage(InstanceData instanceData, DateTime timestamp)
|
||||
{
|
||||
// Store the process details
|
||||
ProcessName = instanceData.InstanceName;
|
||||
|
||||
// Store the initial data
|
||||
LastFound = timestamp;
|
||||
LastSample = instanceData.Sample;
|
||||
|
||||
// We start out as not valid
|
||||
UsageValid = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Usage update
|
||||
|
||||
internal void UpdateCpuUsage(InstanceData instanceData, DateTime timestamp)
|
||||
{
|
||||
// Get the new sample
|
||||
var newSample = instanceData.Sample;
|
||||
|
||||
// Calculate percent usage
|
||||
PercentUsage = CounterSample.Calculate(LastSample, newSample) / Environment.ProcessorCount;
|
||||
|
||||
// Update the last sample and timestmap
|
||||
LastSample = newSample;
|
||||
LastFound = timestamp;
|
||||
|
||||
// Usage is now valid
|
||||
UsageValid = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,13 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FloatingStatusWindowLibrary">
|
||||
<HintPath>..\FloatingStatusWindowLibrary\FloatingStatusWindowLibrary\bin\Debug\FloatingStatusWindowLibrary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
@@ -57,8 +57,11 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="WindowSource.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ProcessCpuUsage.cs" />
|
||||
<Compile Include="ProcessCpuUsageWatcher.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -85,6 +88,9 @@
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\ApplicationIcon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
157
ProcessCpuUsageWatcher.cs
Normal file
157
ProcessCpuUsageWatcher.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow
|
||||
{
|
||||
public class ProcessCpuUsageWatcher
|
||||
{
|
||||
#region Update delegate
|
||||
|
||||
public delegate void ProcessListUpdatedDelegate(Dictionary<string, ProcessCpuUsage> currentProcessList);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Member variables
|
||||
|
||||
private Dispatcher _dispatcher;
|
||||
private Timer _processUpdateTimer;
|
||||
private ProcessListUpdatedDelegate _processListUpdatedCallback;
|
||||
private PerformanceCounterCategory _processCategory;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public Dictionary<string, ProcessCpuUsage> CurrentProcessList;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialize and terminate
|
||||
|
||||
public void Initialize(TimeSpan updateInterval, ProcessListUpdatedDelegate callback)
|
||||
{
|
||||
_dispatcher = Dispatcher.CurrentDispatcher;
|
||||
|
||||
// Create a new dictionary for the process list
|
||||
CurrentProcessList = new Dictionary<string, ProcessCpuUsage>();
|
||||
|
||||
// Get the category for process performance info
|
||||
_processCategory = PerformanceCounterCategory.GetCategories().FirstOrDefault(category => category.CategoryName == "Process");
|
||||
|
||||
if (_processCategory == null)
|
||||
return;
|
||||
|
||||
// Read the entire category
|
||||
InstanceDataCollectionCollection processCategoryData = _processCategory.ReadCategory();
|
||||
|
||||
// Get the processor time data
|
||||
InstanceDataCollection processorTimeData = processCategoryData["% processor time"];
|
||||
|
||||
if (processorTimeData == null || processorTimeData.Values == null)
|
||||
return;
|
||||
|
||||
// Loop over each instance and add it to the list
|
||||
foreach (InstanceData instanceData in processorTimeData.Values)
|
||||
{
|
||||
// Create a new process usage object
|
||||
var processCpuUsage = new ProcessCpuUsage(instanceData);
|
||||
|
||||
// Add to the list
|
||||
CurrentProcessList.Add(processCpuUsage.ProcessName, processCpuUsage);
|
||||
}
|
||||
|
||||
// Save the update callback
|
||||
_processListUpdatedCallback = callback;
|
||||
|
||||
// Create a timer to update the process list
|
||||
_processUpdateTimer = new Timer(updateInterval.TotalMilliseconds) { AutoReset = false };
|
||||
_processUpdateTimer.Elapsed += HandleProcessUpdateTimerElapsed;
|
||||
_processUpdateTimer.Start();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
// Get rid of the timer
|
||||
_processUpdateTimer.Stop();
|
||||
_processUpdateTimer.Dispose();
|
||||
|
||||
// Clear the callback
|
||||
_processListUpdatedCallback = null;
|
||||
|
||||
// Clear the process list
|
||||
CurrentProcessList = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Timer handling
|
||||
|
||||
private void HandleProcessUpdateTimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
// Update the current process list
|
||||
UpdateCurrentProcessList();
|
||||
|
||||
// Restart the timer
|
||||
_processUpdateTimer.Start();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Process list management
|
||||
|
||||
private void UpdateCurrentProcessList()
|
||||
{
|
||||
// Get a timestamp for the current time that we can use to see if a process was found this check
|
||||
DateTime checkStart = DateTime.Now;
|
||||
|
||||
// Read the entire category
|
||||
InstanceDataCollectionCollection processCategoryData = _processCategory.ReadCategory();
|
||||
|
||||
// Get the processor time data
|
||||
InstanceDataCollection processorTimeData = processCategoryData["% processor time"];
|
||||
|
||||
if (processorTimeData == null || processorTimeData.Values == null)
|
||||
return;
|
||||
|
||||
// Loop over each instance and add it to the list
|
||||
foreach (InstanceData instanceData in processorTimeData.Values)
|
||||
{
|
||||
// See if we already know about this process
|
||||
if (CurrentProcessList.ContainsKey(instanceData.InstanceName))
|
||||
{
|
||||
// Get the previous process usage object
|
||||
ProcessCpuUsage processCpuUsage = CurrentProcessList[instanceData.InstanceName];
|
||||
|
||||
// Update the CPU usage with new data
|
||||
processCpuUsage.UpdateCpuUsage(instanceData, checkStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new CPU usage object
|
||||
var processCpuUsage = new ProcessCpuUsage(instanceData, checkStart);
|
||||
|
||||
// Add it to the list
|
||||
CurrentProcessList.Add(processCpuUsage.ProcessName, processCpuUsage);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a list of cached processes we haven't found this check
|
||||
var oldProcessList = (from processCpuUsage in CurrentProcessList
|
||||
where processCpuUsage.Value.LastFound != checkStart
|
||||
select processCpuUsage.Key).ToList();
|
||||
|
||||
// Loop over the list and remove the old process
|
||||
foreach (var key in oldProcessList)
|
||||
CurrentProcessList.Remove(key);
|
||||
|
||||
// Invoke the callback with the new current process list
|
||||
_dispatcher.InvokeAsync(() => _processListUpdatedCallback.Invoke(CurrentProcessList));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
74
Properties/Resources.Designer.cs
generated
74
Properties/Resources.Designer.cs
generated
@@ -8,8 +8,8 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow.Properties
|
||||
{
|
||||
namespace ProcessCpuUsageStatusWindow.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -22,28 +22,23 @@ namespace ProcessCpuUsageStatusWindow.Properties
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProcessCpuUsageStatusWindow.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
@@ -56,16 +51,59 @@ namespace ProcessCpuUsageStatusWindow.Properties
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon ApplicationIcon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("ApplicationIcon", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to CPU: {0,4:f1}% - Total.
|
||||
/// </summary>
|
||||
internal static string FooterLine {
|
||||
get {
|
||||
return ResourceManager.GetString("FooterLine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to .
|
||||
/// </summary>
|
||||
internal static string HeaderLine {
|
||||
get {
|
||||
return ResourceManager.GetString("HeaderLine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Loading....
|
||||
/// </summary>
|
||||
internal static string Loading {
|
||||
get {
|
||||
return ResourceManager.GetString("Loading", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to CPU: {1,4:f1}% - {0}.
|
||||
/// </summary>
|
||||
internal static string ProcessLine {
|
||||
get {
|
||||
return ResourceManager.GetString("ProcessLine", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
@@ -60,6 +60,7 @@
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
@@ -68,9 +69,10 @@
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
@@ -85,9 +87,10 @@
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -109,9 +112,25 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="ApplicationIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ApplicationIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="FooterLine" xml:space="preserve">
|
||||
<value>CPU: {0,4:f1}% - Total</value>
|
||||
</data>
|
||||
<data name="HeaderLine" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Loading" xml:space="preserve">
|
||||
<value>Loading...</value>
|
||||
</data>
|
||||
<data name="ProcessLine" xml:space="preserve">
|
||||
<value>CPU: {1,4:f1}% - {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
50
Properties/Settings.Designer.cs
generated
50
Properties/Settings.Designer.cs
generated
@@ -8,23 +8,55 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow.Properties
|
||||
{
|
||||
namespace ProcessCpuUsageStatusWindow.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("3")]
|
||||
public int ProcessCount {
|
||||
get {
|
||||
return ((int)(this["ProcessCount"]));
|
||||
}
|
||||
set {
|
||||
this["ProcessCount"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("00:00:02")]
|
||||
public global::System.TimeSpan UpdateInterval {
|
||||
get {
|
||||
return ((global::System.TimeSpan)(this["UpdateInterval"]));
|
||||
}
|
||||
set {
|
||||
this["UpdateInterval"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string WindowSettings {
|
||||
get {
|
||||
return ((string)(this["WindowSettings"]));
|
||||
}
|
||||
set {
|
||||
this["WindowSettings"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ProcessCpuUsageStatusWindow.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="ProcessCount" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">3</Value>
|
||||
</Setting>
|
||||
<Setting Name="UpdateInterval" Type="System.TimeSpan" Scope="User">
|
||||
<Value Profile="(Default)">00:00:02</Value>
|
||||
</Setting>
|
||||
<Setting Name="WindowSettings" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
BIN
Resources/ApplicationIcon.ico
Normal file
BIN
Resources/ApplicationIcon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
113
WindowSource.cs
Normal file
113
WindowSource.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using FloatingStatusWindowLibrary;
|
||||
using ProcessCpuUsageStatusWindow.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ProcessCpuUsageStatusWindow
|
||||
{
|
||||
public class WindowSource : IWindowSource, IDisposable
|
||||
{
|
||||
private readonly FloatingStatusWindow _floatingStatusWindow;
|
||||
private readonly ProcessCpuUsageWatcher _processCpuUsageWatcher;
|
||||
|
||||
internal WindowSource()
|
||||
{
|
||||
_floatingStatusWindow = new FloatingStatusWindow(this);
|
||||
_floatingStatusWindow.SetText(Resources.Loading);
|
||||
|
||||
_processCpuUsageWatcher = new ProcessCpuUsageWatcher();
|
||||
_processCpuUsageWatcher.Initialize(Settings.Default.UpdateInterval, UpdateDisplay);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_processCpuUsageWatcher.Terminate();
|
||||
|
||||
_floatingStatusWindow.Save();
|
||||
_floatingStatusWindow.Dispose();
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "Process CPU Usage"; }
|
||||
}
|
||||
|
||||
public System.Drawing.Icon Icon
|
||||
{
|
||||
get { return Resources.ApplicationIcon; }
|
||||
}
|
||||
|
||||
public string WindowSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
return Settings.Default.WindowSettings;
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings.Default.WindowSettings = value;
|
||||
Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
|
||||
#region Display updating
|
||||
|
||||
private static class PredefinedProcessName
|
||||
{
|
||||
public const string Total = "_Total";
|
||||
public const string Idle = "Idle";
|
||||
}
|
||||
|
||||
private void UpdateDisplay(Dictionary<string, ProcessCpuUsage> currentProcessList)
|
||||
{
|
||||
// Filter the process list to valid ones and exclude the idle and total values
|
||||
var validProcessList = (currentProcessList.Values.Where(
|
||||
process =>
|
||||
process.UsageValid && process.ProcessName != PredefinedProcessName.Total &&
|
||||
process.ProcessName != PredefinedProcessName.Idle)).ToList();
|
||||
|
||||
// Calculate the total usage by adding up all the processes we know about
|
||||
var totalUsage = validProcessList.Sum(process => process.PercentUsage);
|
||||
|
||||
// Sort the process list by usage and take only the top few
|
||||
var sortedProcessList = (validProcessList.OrderByDescending(process => process.PercentUsage)).Take(Settings.Default.ProcessCount);
|
||||
|
||||
// Create a new string builder
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
||||
// Add the header line (if any)
|
||||
if (Resources.HeaderLine.Length > 0)
|
||||
{
|
||||
stringBuilder.AppendFormat(Resources.HeaderLine, totalUsage);
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
|
||||
// Loop over all processes in the sorted list
|
||||
foreach (ProcessCpuUsage processCpuUsage in sortedProcessList)
|
||||
{
|
||||
// Move to the next line if it isn't the first line
|
||||
if (stringBuilder.Length != 0)
|
||||
stringBuilder.AppendLine();
|
||||
|
||||
// Format the process information into a string to display
|
||||
stringBuilder.AppendFormat(Resources.ProcessLine, processCpuUsage.ProcessName, processCpuUsage.PercentUsage);
|
||||
}
|
||||
|
||||
// Add the footer line (if any)
|
||||
if (Resources.FooterLine.Length > 0)
|
||||
{
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.AppendFormat(Resources.FooterLine, totalUsage);
|
||||
}
|
||||
|
||||
// Update the window with the text
|
||||
_floatingStatusWindow.SetText(stringBuilder.ToString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user