Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion LiteMonitor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<PlatformTarget>x64</PlatformTarget>
<ApplicationIcon>resources\assets\app.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<PublishSingleFile Condition="'$(RuntimeIdentifier)' != ''">true</PublishSingleFile>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>

Expand All @@ -19,7 +22,7 @@


<ItemGroup>
<PackageReference Include="LibreHardwareMonitorLib" Version="0.9.6" />
<PackageReference Include="LibreHardwareMonitorLib" Version="0.9.7-pre675" />
<PackageReference Include="System.Text.Json" Version="9.0.10" />
</ItemGroup>

Expand Down
41 changes: 41 additions & 0 deletions build/LiteMonitor.iss
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#define MyAppName "LiteMonitor"
#define MyAppVersion "1.3.4"
#define MyAppPublisher "Diorser"
#define MyAppExeName "LiteMonitor.exe"

[Setup]
AppId={{8A6A4E34-36AF-430E-B42E-54793F51DE79}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
PrivilegesRequired=admin
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
OutputDir=..\artifacts\installer
OutputBaseFilename=LiteMonitor_Setup_{#MyAppVersion}_x64
SetupIconFile=..\resources\assets\app.ico
Compression=lzma2/ultra64
SolidCompression=yes
WizardStyle=modern
UninstallDisplayIcon={app}\{#MyAppExeName}
CloseApplications=yes

[Languages]
Name: "chinesesimp"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "创建桌面快捷方式"; GroupDescription: "附加任务:"; Flags: unchecked

[Files]
Source: "..\artifacts\publish-stable\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\卸载 {#MyAppName}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "启动 {#MyAppName}"; Flags: nowait postinstall skipifsilent
5 changes: 4 additions & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@
"TaskbarHoverShowAll": "Hover Details",
"TaskbarStyle": "Style",
"TaskbarMonitor": "Monitor",
"TaskbarMonitorSettings": "Screen Selection",
"TaskbarMonitorTip": "Choose which screens should show the taskbar widget. Auto mode follows the primary taskbar only.",
"TaskbarAllScreens": "Show On All Screens",
"TaskbarStyleBold": "Big",
"TaskbarStyleRegular": "Small",
"TaskbarAlign": "Position",
Expand Down Expand Up @@ -240,4 +243,4 @@
"PluginAddTarget": "+ Add Target",
"PluginDeleteConfirm": "Delete this plugin copy?"
}
}
}
5 changes: 4 additions & 1 deletion resources/lang/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@
"TaskbarHoverShowAll": "滑鼠懸停顯示詳情",
"TaskbarStyle": "工作列樣式",
"TaskbarMonitor": "顯示器螢幕",
"TaskbarMonitorSettings": "螢幕選擇",
"TaskbarMonitorTip": "可勾選工作列顯示在哪些螢幕上;勾選「自動模式」時,將只跟隨主螢幕工作列。",
"TaskbarAllScreens": "所有螢幕都顯示",
"TaskbarStyleBold": "大字模式",
"TaskbarStyleRegular": "小字模式",
"TaskbarAlign": "顯示位置",
Expand Down Expand Up @@ -238,4 +241,4 @@
"PluginAddTarget": "+ 新增監控目標",
"PluginDeleteConfirm": "確定要刪除此插件副本嗎?"
}
}
}
5 changes: 4 additions & 1 deletion resources/lang/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@
"TaskbarHoverShowAll": "鼠标悬停显示详情",
"TaskbarStyle": "任务栏样式",
"TaskbarMonitor": "显示器屏幕",
"TaskbarMonitorSettings": "显示屏选择",
"TaskbarMonitorTip": "可勾选任务栏显示在哪些屏幕上;勾选“自动模式”时,将只跟随主屏任务栏。",
"TaskbarAllScreens": "所有屏幕都显示",
"TaskbarStyleBold": "大字模式",
"TaskbarStyleRegular": "小字模式",
"TaskbarAlign": "显示位置",
Expand Down Expand Up @@ -240,4 +243,4 @@
"PluginAddTarget": "+ 添加新监控目标",
"PluginDeleteConfirm": "确定要删除此插件副本吗?"
}
}
}
5 changes: 5 additions & 0 deletions src/Core/Actions/SettingsChanger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public static void Merge(Settings live, Settings draft)
live.PluginInstances = System.Text.Json.JsonSerializer.Deserialize<List<PluginInstanceConfig>>(json) ?? new List<PluginInstanceConfig>();
continue;
}
if (p.Name == "TaskbarMonitorDevices")
{
live.TaskbarMonitorDevices = new List<string>(draft.TaskbarMonitorDevices ?? new List<string>());
continue;
}
if (p.Name == "Thresholds")
{
// 阈值是 Class 类型 (ThresholdsSet),必须深拷贝
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public class Settings

// ★★★ 新增:指定任务栏显示的屏幕设备名 ("" = 自动/主屏) ★★★
public string TaskbarMonitorDevice { get; set; } = "";
public List<string> TaskbarMonitorDevices { get; set; } = new List<string>();
public bool TaskbarShowOnAllScreens { get; set; } = false;

// 任务栏行为配置
public bool TaskbarClickThrough { get; set; } = false; // 鼠标穿透
Expand Down
42 changes: 40 additions & 2 deletions src/System/HardwareMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ private void InitializeAsync()
_perfCounterManager.InitializeAsync();

// 这句耗时 4-5 秒,但在执行过程中,硬件会陆续添加到 _computer.Hardware
_computer.Open();
OpenComputerSafe();

// ★★★ T0+级修复:彻底禁用历史记录,解决 SensorValue[] 飙升 ★★★
// 必须在 Open() 之后调用,此时传感器才被创建
Expand Down Expand Up @@ -442,7 +442,7 @@ private void ReloadComputerSafe()
_computer.Hardware.Clear();
}

_computer.Open();
OpenComputerSafe();

DisableSensorHistory();
}
Expand All @@ -467,6 +467,44 @@ private void DisableSensorHistory()
catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"[MemoryFix] Failed: {ex.Message}"); }
}

private void OpenComputerSafe()
{
try
{
_computer.Open();
}
catch (ArgumentNullException ex) when (IsMutexBootstrapFailure(ex))
{
System.Diagnostics.Debug.WriteLine($"[HardwareMonitor] Computer.Open mutex bootstrap failed, retrying in compatibility mode: {ex.Message}");
OpenComputerWithoutMutex();
}
}

private void OpenComputerWithoutMutex()
{
var type = typeof(Computer);
var addGroups = type.GetMethod("AddGroups", BindingFlags.Instance | BindingFlags.NonPublic);
var openField = type.GetField("_open", BindingFlags.Instance | BindingFlags.NonPublic);

if (addGroups == null || openField == null)
throw new MissingMemberException("LibreHardwareMonitor compatibility entry points were not found.");

bool isOpen = openField.GetValue(_computer) as bool? ?? false;
if (!isOpen)
{
addGroups.Invoke(_computer, null);
openField.SetValue(_computer, true);
}
}

private static bool IsMutexBootstrapFailure(ArgumentNullException ex)
{
if (!string.Equals(ex.ParamName, "identity", StringComparison.OrdinalIgnoreCase))
return false;

return ex.StackTrace?.Contains("LibreHardwareMonitor.Hardware.Mutexes", StringComparison.Ordinal) == true;
}

// 递归更新子硬件,确保 SuperIO 刷新
private void UpdateWithSubHardware(IHardware hw)
{
Expand Down
67 changes: 66 additions & 1 deletion src/System/HardwareServices/SensorMap.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using LibreHardwareMonitor.Hardware;
using LiteMonitor.src.Core;

Expand Down Expand Up @@ -277,9 +279,72 @@ void RegisterTo(IHardware hw)
_lastMapBuild = DateTime.Now;
// ★★★ [优化 3] 指纹记录已移除 ★★★
}

WriteDiagnostics(computer, newMap, newGpu, newCpuCache);
}

// 复用 HardwareRules 的字符串匹配,避免重复造轮子
public static bool Has(string source, string sub) => HardwareRules.Has(source, sub);

private static void WriteDiagnostics(
Computer computer,
Dictionary<string, ISensor> newMap,
IHardware? newGpu,
List<CpuCoreSensors> newCpuCache)
{
if (!string.Equals(Environment.GetEnvironmentVariable("LITEMONITOR_DIAG"), "1", StringComparison.OrdinalIgnoreCase))
return;

try
{
var sb = new StringBuilder(8192);
sb.AppendLine("==== LiteMonitor Hardware Diagnostics ====");
sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
sb.AppendLine();
sb.AppendLine("[Selected]");
sb.AppendLine($"GPU={newGpu?.Name ?? "<null>"}");
sb.AppendLine($"CPUCoreCache={newCpuCache.Count}");
sb.AppendLine();
sb.AppendLine("[Mapped Keys]");

foreach (var kv in newMap.OrderBy(x => x.Key, StringComparer.OrdinalIgnoreCase))
{
string hwName = kv.Value.Hardware?.Name ?? "<unknown>";
string sensorName = kv.Value.Name ?? "<unknown>";
string sensorType = kv.Value.SensorType.ToString();
string value = kv.Value.Value?.ToString("0.###") ?? "null";
sb.AppendLine($"{kv.Key} => {sensorType} | {sensorName} [{hwName}] | {value}");
}

sb.AppendLine();
sb.AppendLine("[Hardware Tree]");
foreach (var hw in computer.Hardware)
{
DumpHardware(sb, hw, 0);
}

File.WriteAllText(Path.Combine(AppContext.BaseDirectory, "hardware_diagnostic.log"), sb.ToString(), Encoding.UTF8);
}
catch
{
}
Comment on lines +337 to +341
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

诊断日志写入位置使用 AppContext.BaseDirectory:应用安装到 Program Files 时通常没有写权限,开启 LITEMONITOR_DIAG=1 也可能无法生成日志且异常被吞掉。建议改为写到用户可写目录(如 %LOCALAPPDATA%/LiteMonitor%TEMP%),并至少在 catch 中输出 Debug/Trace 信息方便定位。

Copilot uses AI. Check for mistakes.
}

private static void DumpHardware(StringBuilder sb, IHardware hw, int depth)
{
string indent = new string(' ', depth * 2);
sb.AppendLine($"{indent}- {hw.HardwareType}: {hw.Name}");

foreach (var s in hw.Sensors.OrderBy(x => x.SensorType).ThenBy(x => x.Name, StringComparer.OrdinalIgnoreCase))
{
string value = s.Value?.ToString("0.###") ?? "null";
sb.AppendLine($"{indent} * {s.SensorType}: {s.Name} = {value}");
}

foreach (var sub in hw.SubHardware)
{
DumpHardware(sb, sub, depth + 1);
}
}
}
}
}
8 changes: 5 additions & 3 deletions src/UI/Helpers/TaskbarBizHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class TaskbarBizHelper
private readonly Form _form;
private readonly Settings _cfg;
private readonly TaskbarWinHelper _winHelper;
private readonly string _targetDevice;

private Rectangle _taskbarRect = Rectangle.Empty;
private int _taskbarHeight = 32;
Expand All @@ -33,11 +34,12 @@ public class TaskbarBizHelper
public Color TransparentKey => _transparentKey;
public bool LastIsLightTheme => _lastIsLightTheme;

public TaskbarBizHelper(Form form, Settings cfg, TaskbarWinHelper winHelper)
public TaskbarBizHelper(Form form, Settings cfg, TaskbarWinHelper winHelper, string targetDevice)
{
_form = form;
_cfg = cfg;
_winHelper = winHelper;
_targetDevice = targetDevice;
_isWin11 = Environment.OSVersion.Version >= new Version(10, 0, 22000);
}

Expand Down Expand Up @@ -84,7 +86,7 @@ public void CheckTheme(bool force = false)
// =================================================================
public void FindHandles()
{
var handles = _winHelper.FindHandles(_cfg.TaskbarMonitorDevice);
var handles = _winHelper.FindHandles(_targetDevice);
_hTaskbar = handles.hTaskbar;
_hTray = handles.hTray;
}
Expand All @@ -104,7 +106,7 @@ public void AttachToTaskbar()

public void UpdateTaskbarRect()
{
_taskbarRect = _winHelper.GetTaskbarRect(_hTaskbar, _cfg.TaskbarMonitorDevice);
_taskbarRect = _winHelper.GetTaskbarRect(_hTaskbar, _targetDevice);
_taskbarHeight = Math.Max(24, _taskbarRect.Height);
}

Expand Down
2 changes: 1 addition & 1 deletion src/UI/Helpers/TaskbarWinHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ private IntPtr FindSecondaryTaskbar(Screen screen)
if (screen.Bounds.Contains(r.Location) || screen.Bounds.IntersectsWith(r))
return hWnd;
}
return FindWindow("Shell_TrayWnd", null);
return IntPtr.Zero;
Comment on lines 215 to +218
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FindSecondaryTaskbar 找不到二屏任务栏时现在返回 IntPtr.Zero;上层仍会创建并 Show TaskbarForm,但由于 AttachToTaskbar 直接 return,窗口可能以普通无边框窗体的形式浮在屏幕左上角/不可预期位置。建议在 FindHandles/ToggleTaskbar 层面检测二屏无任务栏(例如 Windows 未开启“在所有显示器上显示任务栏”)时:要么回退到主任务栏,要么不要创建该 device 的 TaskbarForm 并给出提示。

Copilot uses AI. Check for mistakes.
}

public Rectangle GetTaskbarRect(IntPtr hTaskbar, string targetDevice)
Expand Down
Loading
Loading