Skip to content

Commit f7b3cc3

Browse files
authored
Merge pull request #5 from sMkTools/rel/3.2.0
2 parents 90daf2b + dbde6ba commit f7b3cc3

44 files changed

Lines changed: 1474 additions & 557 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<div align="center">
2-
<img alt="GitHub Latest Release" src="https://img.shields.io/github/v/release/sMkTools/sMkTaskManager?label=Latest%20Release" />
3-
<img alt="GitHub License" src="https://img.shields.io/github/license/sMkTools/sMkTaskManager?label=License" />
4-
<img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/sMkTools/sMkTaskManager/total?label=Downloads" />
5-
<img alt="WinForms Badge" src="https://img.shields.io/badge/Win-Forms-purple" />
6-
<img alt="Admin Badge" src="https://img.shields.io/badge/Admin-Only-red" />
2+
<a href="#"><img alt="GitHub Latest Release" src="https://img.shields.io/github/v/release/sMkTools/sMkTaskManager?label=Latest%20Release" /></a>
3+
<a href="#"><img alt="GitHub License" src="https://img.shields.io/github/license/sMkTools/sMkTaskManager?label=License" /></a>
4+
<a href="#"><img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/sMkTools/sMkTaskManager/total?label=Downloads" /></a>
5+
<a href="#"><img alt="WinForms Badge" src="https://img.shields.io/badge/Win-Forms-purple" /></a>
6+
<a href="#"><img alt="Admin Badge" src="https://img.shields.io/badge/Admin-Only-red" /></a>
77
</div>
88

99
# sMk Task Manager
@@ -25,16 +25,17 @@ Most likely you will see pieces of code that are UGLY for experienced programmer
2525

2626
## Main Features
2727

28+
+ A very nostalgic but extremly cool System Properties pages.
2829
+ Detailed overview of all running processes activity with highlighting.
2930
+ System performance metrics, CPU, Memory, I/O, Disk, Network.
3031
+ GPU performance metrics, Engines, Memory, Power, Temperatures.
3132
+ Network usage statistics, global and per network interface.
32-
+ List of active connections by process, and traffic.
33+
+ List of active connections by process and their traffic usage.
3334
+ List of listening ports, and which processes is holding it.
3435
+ List and control services pretty much as services.msc.
35-
+ Device Manager, pretty much as devmgr.msc.
36+
+ Hardware Device Manager, pretty much as devmgr.msc.
3637
+ List of user and windows terminal services sessions.
37-
+ Intuitive to legacy users (not millennials) as a default Task Manager.
38+
+ Intuitive to legacy users (not millennials) as a legacy Task Manager.
3839
+ Customizable graphs, column details and layouts.
3940
+ Small, portable, fast-ish, and 100% Free to use and modify.
4041

@@ -55,7 +56,8 @@ Most likely you will see pieces of code that are UGLY for experienced programmer
5556
## System requirements
5657

5758
It seems odd to talk about requirements nowadays but let’s keep it simple and basic.
58-
**Windows 10 or higher - 64 Bits.** - I have ditched and no longer test it on 32 Bits.
59+
**[Windows 10 or higher - 64 Bits](https://www.microsoft.com/software-download/windows11)** - I have ditched and no longer test it on 32 Bits.
60+
**[.NET Desktop Runtime 7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)** - Currently targeting .NET Desktop 7.0.*
5961
On the other hand, if you really like this application and need to run on older legacy systems, I can provide you with the old version which stills runs on Windows XP onwards.
6062

6163
## Administrative Privileges
@@ -82,7 +84,7 @@ These features were originally implemented on older versions, but I removed the
8284
## Future Features
8385

8486
+ DarkMode (someday, when WinForms properly supports it).
85-
+ Better Graphs customization and profiles.
87+
+ Better graphs customization and profiles.
8688
+ WSL Instances lists and control.
8789
+ Hyper-V Machine lists and control.
8890
+ More detailed Disk Performance and Usage monitor.

src/Classes/APIs.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,8 @@ public DEVPROPKEY(string strGuid, int pid) {
13501350
internal static extern unsafe NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, ref SYSTEM_PERFORMANCE_INFORMATION SystemInformation, int SystemInformationLength, out int returnLength);
13511351
[System.Security.SuppressUnmanagedCodeSecurity()] [DllImport("ntdll.dll", SetLastError = true)]
13521352
internal static extern unsafe NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, out int returnLength);
1353+
[System.Security.SuppressUnmanagedCodeSecurity()] [DllImport("kernel32.dll", SetLastError = true)]
1354+
internal static extern bool GetPhysicallyInstalledSystemMemory(out long TotalMemoryInKilobytes);
13531355
[System.Security.SuppressUnmanagedCodeSecurity()] [DllImport("psapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
13541356
internal static extern unsafe bool EnumPageFiles(EnumPageFilesProc proc, IntPtr lpContext);
13551357
internal delegate bool EnumPageFilesProc(IntPtr lpContext, ref PAGE_FILE_INFORMATION Info, string Name);

src/Classes/TaskManagerConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public TaskManagerConnection(string connIdent) : this() {
5252
public IPEndPoint Local { get => _Local; set { SetField(ref _Local, value, nameof(Local), new[] { nameof(LocalAddr), nameof(LocalPort) }); } }
5353
public IPEndPoint Remote { get => _Remote; set { SetField(ref _Remote, value, nameof(Remote), new[] { nameof(RemoteAddr), nameof(RemotePort) }); } }
5454
public string LocalAddr { get => isIPv6 ? "[" + _Local.Address.ToString() + "]" : _Local.Address.ToString(); }
55-
public string LocalPort { get => _Remote.Port.ToString(); }
55+
public string LocalPort { get => _Local.Port.ToString(); }
5656
public string RemoteAddr { get => isIPv6 ? "[" + _Remote.Address.ToString() + "]" : _Remote.Address.ToString(); }
5757
public string RemotePort { get => _Remote.Port.ToString(); }
5858
public ConnectionState State { get => _State; set { SetField(ref _State, value, nameof(State), new[] { nameof(StateString) }); } }

src/Classes/TaskManagerProcess.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,16 +451,16 @@ private string FormatValue(ulong value, FormatValueTypes format, bool skipBPI =
451451
case FormatValueTypes.Literal: return value.ToString();
452452
case FormatValueTypes.Number: return string.Format("{0:#,0}", value);
453453
case FormatValueTypes.Bytes: return string.Format("{0:#,0}", value) + " B";
454-
case FormatValueTypes.KBytes: return string.Format("{0:#,0}", value / 1024) + " K";
455-
case FormatValueTypes.MBytes: return string.Format("{0:#,0}", value / 1024 / 1024) + " M";
456-
case FormatValueTypes.Kbps: return string.Format("{0:#,0.0}", value / 1024) + " Kb/s";
454+
case FormatValueTypes.KBytes: return string.Format("{0:#,0}", value / 1024d) + " K";
455+
case FormatValueTypes.MBytes: return string.Format("{0:#,0}", value / 1024d / 1024d) + " M";
456+
case FormatValueTypes.Kbps: return string.Format("{0:#,0.0}", value / 1024d) + " Kb/s";
457457
case FormatValueTypes.AutoBytes:
458458
if (value < 10240) {
459459
return string.Format("{0:#,0}", value) + " B";
460460
} else if (value < 1024000) {
461-
return string.Format("{0:#,0}", value / 1024) + " K";
461+
return string.Format("{0:#,0.0}", value / 1024d) + " K";
462462
} else {
463-
return string.Format("{0:#,0}", value / 1024 / 1024) + " M";
463+
return string.Format("{0:#,0.0}", (value / 1024d / 1024d)) + " M";
464464
}
465465
default: return value.ToString();
466466
}

src/Classes/TaskManagerService.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ namespace sMkTaskManager.Classes;
88

99
[SupportedOSPlatform("windows")]
1010
internal class TaskManagerService : IEquatable<TaskManagerService>, INotifyPropertyChanged {
11-
1211
private ServiceController _BaseService;
1312
private ServiceControllerStatus _StatusCode;
1413
private ServiceStartMode _StartupCode;
1514
private readonly string _Ident;
1615
private string _PID = "", _Name = "", _Description = "", _Logon = "", _ImagePath = "", _CommandLine = "";
17-
private Color _BackColor = Color.Empty;
16+
private Color _ForeColor = Color.Empty, _BackColor = Color.Empty;
1817
private int _ImageIndex = 0;
1918

2019
public TaskManagerService(string serviceIdent) {
@@ -50,6 +49,7 @@ public string Logon {
5049
public ServiceControllerStatus StatusCode { get => _StatusCode; set { SetField(ref _StatusCode, value, nameof(Status)); } }
5150
public string Startup => _StartupCode.ToString();
5251
public ServiceStartMode StartupCode { get => _StartupCode; set { SetField(ref _StartupCode, value, nameof(Startup)); } }
52+
public Color ForeColor { get => _ForeColor; set { SetField(ref _ForeColor, value); } }
5353
public Color BackColor { get => _BackColor; set { SetField(ref _BackColor, value); } }
5454
public int ImageIndex { get => _ImageIndex; set { SetField(ref _ImageIndex, value); } }
5555
public ServiceController[] DependentServices => (_BaseService == null) ? Array.Empty<ServiceController>() : _BaseService.DependentServices;
@@ -89,6 +89,7 @@ public void Update() {
8989
ImageIndex = (si.StartType == ServiceStartMode.Disabled) ? 2 : ((_BaseService.Status == ServiceControllerStatus.Running) ? 0 : 1);
9090
if (si.Description != "") { Description = si.Description!; }
9191
PID = (si.ProcessID == 0) ? "" : si.ProcessID.ToString();
92+
ForeColor = StartupCode == ServiceStartMode.Disabled ? SystemColors.GrayText : Color.Empty;
9293

9394
if (NotifyChanges && LastUpdated <= LastChanged) {
9495
BackColor = Settings.Highlights.ChangingItems ? Settings.Highlights.ChangingColor : Color.Empty;
@@ -201,6 +202,9 @@ public struct SERVICE_INFO {
201202
private void MyPropertyChanged(object? sender, PropertyChangedEventArgs e) {
202203
if (!NotifyChanges) return;
203204
if (e.PropertyName == null) return;
205+
if (e.PropertyName.Equals("LastChanged")) return;
206+
if (e.PropertyName.Equals("LastUpdated")) return;
207+
if (e.PropertyName.Equals("PreviousUpdate")) return;
204208
LastChanged = LastUpdated;
205209
}
206210
private void OnPropertyChanged(PropertyChangedEventArgs e) { if (NotifyChanges) PropertyChanged?.Invoke(this, e); }
@@ -364,5 +368,6 @@ public bool Contains(string serviceIdent) {
364368
}
365369
return null;
366370
}
371+
public TaskManagerService? this[string serviceIdent] => Items.Where(_ => _.Ident == serviceIdent).FirstOrDefault();
367372

368373
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System.Collections;
2+
using System.Runtime.Versioning;
3+
using Microsoft.Win32;
4+
namespace sMkTaskManager.Classes;
5+
6+
[SupportedOSPlatform("windows")]
7+
internal class TaskManagerSystemProps {
8+
public string WindowsName { get; private set; }
9+
public string WindowsEdition { get; private set; }
10+
public string WindowsVersion { get; private set; }
11+
public DateTime InstallDate { get; private set; }
12+
public string RegisterUser { get; private set; }
13+
public string RegisterCompany { get; private set; }
14+
public string RegisterKey { get; private set; }
15+
public string SystemManufacturer { get; private set; }
16+
public string SystemProductName { get; private set; }
17+
public string ProcessorVendor { get; private set; }
18+
public string ProcessorName { get; private set; }
19+
public string ProcessorFamily { get; private set; }
20+
public int ProcessorCount { get; private set; }
21+
public string ProcessorSpeed { get; private set; }
22+
public int TotalMemory { get; private set; }
23+
public bool OEMInfo { get; private set; } = false;
24+
public Image? OEMLogo { get; private set; }
25+
public string OEMManufacturer { get; private set; }
26+
public string OEMSupportPhone { get; private set; }
27+
public string OEMSupportHours { get; private set; }
28+
public string OEMSupportURL { get; private set; }
29+
30+
public void Refresh() {
31+
// Get Windows Version Information
32+
RegistryKey? rk = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", false);
33+
if (rk != null) {
34+
try { WindowsName = $"Microsoft {rk.GetValue("ProductName")}"; } catch { }
35+
try { WindowsEdition = $"{rk.GetValue("EditionID")} Edition"; } catch { }
36+
try { WindowsVersion = $"{rk.GetValue("DisplayVersion")} - Build: {rk.GetValue("CurrentBuild")}.{rk.GetValue("UBR")}"; } catch { }
37+
try { InstallDate = DateTime.UnixEpoch.AddSeconds(Convert.ToInt64(rk.GetValue("InstallDate"))).ToLocalTime(); } catch { }
38+
try { RegisterUser = rk.GetValue("RegisteredOwner")?.ToString()!; } catch { }
39+
try { RegisterCompany = rk.GetValue("RegisteredOrganization")?.ToString()!; } catch { }
40+
try { RegisterKey = DecodeProductKey((byte[])rk.GetValue("DigitalProductId")!); } catch { }
41+
}
42+
rk?.Close();
43+
// Get Processor Information
44+
RegistryKey? rk2 = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0", false);
45+
if (rk2 != null) {
46+
try { ProcessorVendor = rk2.GetValue("VendorIdentifier")?.ToString()!; } catch { }
47+
try { ProcessorName = rk2.GetValue("ProcessorNameString")?.ToString()!; } catch { }
48+
try { ProcessorFamily = rk2.GetValue("Identifier")?.ToString()!; } catch { }
49+
try { ProcessorSpeed = rk2.GetValue("~MHz")?.ToString()!; } catch { }
50+
}
51+
rk2?.Close();
52+
// Get System Information
53+
RegistryKey? rk3 = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\BIOS", false);
54+
if (rk3 != null) {
55+
try { SystemManufacturer = rk3.GetValue("SystemManufacturer")?.ToString()!; } catch { }
56+
try { SystemProductName = rk3.GetValue("SystemProductName")?.ToString()!; } catch { }
57+
}
58+
rk3?.Close();
59+
// Get OEM Information
60+
RegistryKey? rk4 = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation", false);
61+
if (rk4 != null) {
62+
if (File.Exists(rk4.GetValue("Logo")?.ToString()!)) {
63+
try { OEMLogo = Image.FromFile(rk4.GetValue("Logo")?.ToString()!); } catch { OEMLogo = null; }
64+
}
65+
try { OEMManufacturer = rk4.GetValue("Manufacturer")?.ToString()!; } catch { }
66+
try { OEMSupportPhone = rk4.GetValue("SupportPhone")?.ToString()!; } catch { }
67+
try { OEMSupportHours = rk4.GetValue("SupportHours")?.ToString()!; } catch { }
68+
try { OEMSupportURL = rk4.GetValue("SupportURL")?.ToString()!; } catch { }
69+
OEMInfo = (OEMManufacturer != "" || OEMSupportPhone != "" || OEMSupportURL != "");
70+
} else { OEMInfo = false; }
71+
rk4?.Close();
72+
// Get Total Memory
73+
if (API.GetPhysicallyInstalledSystemMemory(out long memKb)) {
74+
TotalMemory = (int)(memKb / 1024 / 1024);
75+
} else { TotalMemory = 0; }
76+
77+
}
78+
private static string DecodeProductKey(byte[] digitalProductId) {
79+
if (digitalProductId == null) return string.Empty;
80+
if (digitalProductId.Length < 20) return string.Empty;
81+
// Offset of first byte of encoded product key in 'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
82+
const int keyStartIndex = 52;
83+
// Offset of last byte of encoded product key in 'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
84+
const int keyEndIndex = keyStartIndex + 15;
85+
// Possible alpha-numeric characters in product key.
86+
char[] digits = new char[] { 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9', };
87+
// Length of decoded product key
88+
const int decodeLength = 29;
89+
// Length of decoded product key in byte-form.
90+
// Each byte represents 2 chars.
91+
const int decodeStringLength = 15;
92+
// Array of containing the decoded product key.
93+
char[] decodedChars = new char[decodeLength];
94+
// Extract byte 52 to 67 inclusive.
95+
ArrayList hexPid = new();
96+
for (int i = keyStartIndex; i <= keyEndIndex; i++) {
97+
hexPid.Add(digitalProductId[i]);
98+
}
99+
for (int i = decodeLength - 1; i >= 0; i--) {
100+
// Every sixth char is a separator.
101+
if ((i + 1) % 6 == 0) {
102+
decodedChars[i] = '-';
103+
} else {
104+
// Do the actual decoding.
105+
int digitMapIndex = 0;
106+
for (int j = decodeStringLength - 1; j >= 0; j--) {
107+
int byteValue = (digitMapIndex << 8) | (byte)hexPid[j]!;
108+
hexPid[j] = (byte)(byteValue / 24);
109+
digitMapIndex = byteValue % 24;
110+
decodedChars[i] = digits[digitMapIndex];
111+
}
112+
}
113+
}
114+
return new string(decodedChars);
115+
}
116+
117+
}

0 commit comments

Comments
 (0)