Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion LiteMonitor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<Content Include="resources\LiteMonitor.Updater.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="使用说明(必读).txt">
<Content Include="使用说明(必读).txt" Condition="Exists('使用说明(必读).txt')">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions resources/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "Disk",
"NetworkSource": "Netz",
"GpuSource": "GPU",
"CpuTempSource": "CPU-Temp-Quelle",
"Auto": "Auto",
"UseWinPerCounters": "Sys Zähler",
"UseWinPerCountersTip": "⚠️Deaktivieren bei Ungenauigkeit. CPU/GPU/RAM/DISK von Sensoren gelesen.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "Disk",
"NetworkSource": "Network",
"GpuSource": "GPU",
"CpuTempSource": "CPU Temp Source",
"Auto": "Auto",
"UseWinPerCounters": "Use Sys Counters",
"UseWinPerCountersTip": "⚠️Disable if inaccurate. CPU/GPU/MEM/DISK read from sensors.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "Disco",
"NetworkSource": "Red",
"GpuSource": "GPU",
"CpuTempSource": "Fuente temp. CPU",
"Auto": "Auto",
"UseWinPerCounters": "Contadores Sistema",
"UseWinPerCountersTip": "⚠️Desactiva si no es exacto. CPU/GPU/RAM/DISCO leídos desde sensores.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@
"DiskSource": "Disque",
"NetworkSource": "Réseau",
"GpuSource": "GPU",
"CpuTempSource": "Source temp. CPU",
"Auto": "Auto",
"UseWinPerCounters": "Compteurs Système",
"UseWinPerCountersTip": "⚠️Désactiver si inexact. CPU/GPU/RAM/DISK lues depuis capteurs.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@
"DiskSource": "ディスク",
"NetworkSource": "ネットワーク",
"GpuSource": "GPU",
"CpuTempSource": "CPU 温度ソース",
"Auto": "自動",
"UseWinPerCounters": "システムカウンター優先",
"UseWinPerCountersTip": "⚠️不正確な場合は無効にしてください。CPU/GPU/RAM/ディスクはセンサーから直接読み取られます。",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "디스크",
"NetworkSource": "네트워크",
"GpuSource": "GPU",
"CpuTempSource": "CPU 온도 소스",
"Auto": "자동",
"UseWinPerCounters": "시스템 카운터 우선",
"UseWinPerCountersTip": "⚠️부정확시 끄세요. CPU/GPU/RAM/디스크는 센서에서 직접 읽습니다.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "Диск",
"NetworkSource": "Сеть",
"GpuSource": "GPU",
"CpuTempSource": "Источник температуры CPU",
"Auto": "Авто",
"UseWinPerCounters": "Системные счетчики",
"UseWinPerCountersTip": "⚠️Отключите при неточности. CPU/GPU/RAM/Диск читаются из датчиков.",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
"DiskSource": "首選磁碟",
"NetworkSource": "首選網卡",
"GpuSource": "首選顯卡",
"CpuTempSource": "CPU 溫度來源",
"Auto": "自動模式",
"UseWinPerCounters": "優先使用系統計數器",
"UseWinPerCountersTip": "⚠️如數據不準可關閉系統計數器,關閉後,CPU使用率、CPU頻率、記憶體占用、磁碟讀取將直讀硬體感測器",
Expand Down
1 change: 1 addition & 0 deletions resources/lang/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"DiskSource": "首选磁盘",
"NetworkSource": "首选网卡",
"GpuSource": "首选显卡",
"CpuTempSource": "CPU温度来源",
"Auto": "自动模式",
"UseWinPerCounters": "优先使用系统计数器",
"UseWinPerCountersTip": "⚠️如数据不准可关闭系统计数器,关闭后,CPU使用率、CPU频率、内存占用、磁盘读取将直读硬件传感器",
Expand Down
1 change: 1 addition & 0 deletions src/Core/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class Settings
public string PreferredCpuFan { get; set; } = "";
public string PreferredCpuPump { get; set; } = ""; // 保存用户选的水冷接口
public string PreferredCaseFan { get; set; } = "";
public string PreferredCpuTemp { get; set; } = "";
public string PreferredMoboTemp { get; set; } = "";

// 主窗体所在的屏幕设备名 (用于记忆上次位置)
Expand Down
1 change: 1 addition & 0 deletions src/Core/SettingsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ public static void InternAllStrings(this Settings settings)
settings.PreferredCpuFan = UIUtils.Intern(settings.PreferredCpuFan);
settings.PreferredCpuPump = UIUtils.Intern(settings.PreferredCpuPump);
settings.PreferredCaseFan = UIUtils.Intern(settings.PreferredCaseFan);
settings.PreferredCpuTemp = UIUtils.Intern(settings.PreferredCpuTemp);
settings.PreferredMoboTemp = UIUtils.Intern(settings.PreferredMoboTemp);

settings.TaskbarFontFamily = UIUtils.Intern(settings.TaskbarFontFamily);
Expand Down
71 changes: 71 additions & 0 deletions src/System/HardwareServices/HardwareScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static class HardwareScanner
private static List<string>? _cachedNetworkList = null;
private static List<string>? _cachedDiskList = null;
private static List<GpuOption>? _cachedGpuOptions = null;
private static List<SensorOption>? _cachedCpuTempOptions = null;
private static List<string>? _cachedMoboTempList = null;

public sealed class GpuOption
Expand All @@ -23,6 +24,13 @@ public sealed class GpuOption
public string Name { get; set; } = "";
}

public sealed class SensorOption
{
public string Label { get; set; } = "";
public string Value { get; set; } = "";
public string Name { get; set; } = "";
}

/// <summary>
/// 清除所有扫描缓存
/// </summary>
Expand All @@ -32,6 +40,7 @@ public static void ClearCache()
_cachedNetworkList = null;
_cachedDiskList = null;
_cachedGpuOptions = null;
_cachedCpuTempOptions = null;
_cachedMoboTempList = null;
}

Expand Down Expand Up @@ -174,6 +183,68 @@ private static List<GpuOption> CloneGpuOptions(List<GpuOption> source)
.ToList();
}

private static List<SensorOption> CloneSensorOptions(List<SensorOption> source)
{
return source
.Select(x => new SensorOption { Label = x.Label, Value = x.Value, Name = x.Name })
.ToList();
}

/// <summary>
/// 列出所有 CPU 温度传感器,供用户在 AMD/多 CPU/多 CCD 场景下手动选择 Entry。
/// </summary>
public static List<SensorOption> ListAllCpuTempOptions(IComputer computer, object syncLock)
{
if (_cachedCpuTempOptions != null && _cachedCpuTempOptions.Count > 0)
return CloneSensorOptions(_cachedCpuTempOptions);

var list = new List<SensorOption>();
lock (syncLock)
{
var cpus = computer.Hardware.Where(h => h.HardwareType == HardwareType.Cpu).ToList();
var nameCounts = cpus
.GroupBy(h => h.Name, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.Count(), StringComparer.OrdinalIgnoreCase);
var nameIndexes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

foreach (var cpu in cpus)
{
string cpuName = cpu.Name ?? "";
nameIndexes.TryGetValue(cpuName, out int currentIndex);
currentIndex++;
nameIndexes[cpuName] = currentIndex;

bool duplicatedName = nameCounts.TryGetValue(cpuName, out int count) && count > 1;
string cpuLabel = duplicatedName ? $"{cpuName} #{currentIndex}" : cpuName;

foreach (var s in cpu.Sensors)
{
if (s.SensorType != SensorType.Temperature) continue;
if (SensorMap.Has(s.Name, "Distance")) continue;

string label = $"{s.Name} [{cpuLabel}]";
string value = s.Identifier?.ToString() ?? "";
if (string.IsNullOrWhiteSpace(value)) value = label;

list.Add(new SensorOption
{
Label = label,
Value = value,
Name = s.Name ?? ""
});
}
}
}

var final = list
.GroupBy(x => x.Value, StringComparer.OrdinalIgnoreCase)
.Select(g => g.First())
.ToList();

if (final.Count > 0) _cachedCpuTempOptions = CloneSensorOptions(final);
return CloneSensorOptions(final);
}

/// <summary>
/// 列出所有风扇传感器 (排除 CPU/GPU 等核心自带风扇,主要针对主板/机箱风扇)
/// </summary>
Expand Down
83 changes: 74 additions & 9 deletions src/System/HardwareServices/HardwareValueProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ public class HardwareValueProvider : IDisposable

private const float AutoMoboTempHardMax = 95f;
private const float ManualMoboTempHardMax = 125f;
private const float CpuTempHardMax = 125f;

// 配置版本追踪,用于自动触发预热
private string _lastPrefCpuTemp = "";
private string _lastPrefCpuFan = "";
private string _lastPrefCpuPump = "";
private string _lastPrefCaseFan = "";
Expand Down Expand Up @@ -63,6 +65,7 @@ public void PreCacheAllSensors(SensorMap map)
var newCache = map.GetInternalMap();

// 记录当前预热的配置版本
_lastPrefCpuTemp = _cfg.PreferredCpuTemp;
_lastPrefCpuFan = _cfg.PreferredCpuFan;
_lastPrefCpuPump = _cfg.PreferredCpuPump;
_lastPrefCaseFan = _cfg.PreferredCaseFan;
Expand All @@ -71,15 +74,16 @@ public void PreCacheAllSensors(SensorMap map)
_lastPrefNet = _cfg.PreferredNetwork;
_lastPrefGpu = _cfg.PreferredGpu ?? "";

// 1. 预查找用户指定的首选传感器 (风扇、水泵、主板温度)
string[] preferredKeys = { "CPU.Fan", "CPU.Pump", "CASE.Fan", "MOBO.Temp" };
// 1. 预查找用户指定的首选传感器 (CPU 温度、风扇、水泵、主板温度)
string[] preferredKeys = { "CPU.Temp", "CPU.Fan", "CPU.Pump", "CASE.Fan", "MOBO.Temp" };
foreach (var key in preferredKeys)
{
string pref = (key == "CPU.Fan") ? _lastPrefCpuFan :
(key == "CPU.Pump") ? _lastPrefCpuPump :
(key == "CASE.Fan") ? _lastPrefCaseFan : _lastPrefMoboTemp;
string pref = key == "CPU.Temp" ? _lastPrefCpuTemp :
key == "CPU.Fan" ? _lastPrefCpuFan :
key == "CPU.Pump" ? _lastPrefCpuPump :
key == "CASE.Fan" ? _lastPrefCaseFan : _lastPrefMoboTemp;

SensorType type = (key == "MOBO.Temp") ? SensorType.Temperature : SensorType.Fan;
SensorType type = (key == "CPU.Temp" || key == "MOBO.Temp") ? SensorType.Temperature : SensorType.Fan;

if (!string.IsNullOrEmpty(pref) && !pref.Contains("自动") && !pref.Contains("Auto"))
{
Expand Down Expand Up @@ -143,6 +147,30 @@ public void PreCacheAllSensors(SensorMap map)
if (string.IsNullOrEmpty(savedString) || savedString.Contains("Auto") || savedString.Contains("自动"))
return null;

ISensor? SearchByIdentifier(IHardware h)
{
foreach (var s in h.Sensors)
{
if (s.SensorType == type &&
string.Equals(s.Identifier?.ToString(), savedString, StringComparison.OrdinalIgnoreCase))
{
return s;
}
}
foreach (var sub in h.SubHardware)
{
var s = SearchByIdentifier(sub);
if (s != null) return s;
}
return null;
}

foreach (var hw in _computer.Hardware)
{
var s = SearchByIdentifier(hw);
if (s != null) return s;
}

int idx = savedString.LastIndexOf('[');
if (idx < 0) return null;

Expand Down Expand Up @@ -199,8 +227,9 @@ public void OnUpdateTickStarted()
_sensorMap.Rebuild(_computer, _cfg);
}

// 自动检测配置变更:如果用户更改了首选风扇/磁盘/显卡,立即自动预热
// 自动检测配置变更:如果用户更改了首选传感器/磁盘/显卡,立即自动预热
if (gpuChanged ||
_lastPrefCpuTemp != _cfg.PreferredCpuTemp ||
_lastPrefCpuFan != _cfg.PreferredCpuFan ||
_lastPrefCpuPump != _cfg.PreferredCpuPump ||
_lastPrefCaseFan != _cfg.PreferredCaseFan ||
Expand Down Expand Up @@ -319,10 +348,22 @@ public void OnUpdateTickStarted()

// 2. CPU.Temp
case "CPU.Temp":
result = _componentProcessor.GetCpuTemp();
bool manualCpuTemp = IsManualCpuTemperatureSelected();
bool hasSelectedCpuTempSensor = _manualSensorCache.TryGetValue("CPU.Temp", out var selectedCpuTemp);

if (manualCpuTemp && hasSelectedCpuTempSensor)
{
result = ReadCpuTemperature(selectedCpuTemp);
}

if (result == null && (!manualCpuTemp || !hasSelectedCpuTempSensor))
{
result = _componentProcessor.GetCpuTemp();
}

if (result == null && _manualSensorCache.TryGetValue("CPU.Temp", out var fallbackT))
{
result = fallbackT.Value;
result = manualCpuTemp ? ReadCpuTemperature(fallbackT) : fallbackT.Value;
}
if (result == null) result = 0f;
break;
Expand Down Expand Up @@ -566,6 +607,30 @@ private bool IsManualMoboTemperatureSelected()
: null;
}

private float? ReadCpuTemperature(ISensor sensor)
{
var raw = sensor.Value;
if (!raw.HasValue || float.IsNaN(raw.Value) || float.IsInfinity(raw.Value) || raw.Value <= 0f || raw.Value > CpuTempHardMax)
{
return _lastValidMap.TryGetValue("CPU.Temp", out float last) &&
last > 0f &&
last <= CpuTempHardMax
? last
: null;
}

_lastValidMap["CPU.Temp"] = raw.Value;
return raw.Value;
}

private bool IsManualCpuTemperatureSelected()
{
string pref = _cfg.PreferredCpuTemp ?? "";
return !string.IsNullOrWhiteSpace(pref) &&
!pref.Contains("自动", StringComparison.OrdinalIgnoreCase) &&
!pref.Contains("Auto", StringComparison.OrdinalIgnoreCase);
}

public void Dispose()
{
}
Expand Down
24 changes: 22 additions & 2 deletions src/UI/Settings/SystemHardwarPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SystemHardwarPage : SettingsPageBase
private Panel _container;

// ★★★ 修复:类型更正为 LiteComboBox ★★★
private LiteComboBox _cbDisk, _cbNet, _cbGpu, _cbMobo;
private LiteComboBox _cbDisk, _cbNet, _cbGpu, _cbCpuTemp, _cbMobo;
private LiteComboBox _cbFanCpu, _cbFanPump, _cbFanCase;

public SystemHardwarPage()
Expand Down Expand Up @@ -55,10 +55,11 @@ private async void PopulateAsyncData()
var taskDisks = Task.Run(() => HardwareScanner.ListAllDisks(HardwareMonitor.Instance.ComputerInstance));
var taskNets = Task.Run(() => HardwareScanner.ListAllNetworks(HardwareMonitor.Instance.ComputerInstance));
var taskGpus = Task.Run(() => HardwareMonitor.ListAllGpuOptions());
var taskCpuTemps = Task.Run(() => HardwareScanner.ListAllCpuTempOptions(HardwareMonitor.Instance.ComputerInstance, HardwareMonitor.Instance.SyncLock));
var taskFans = Task.Run(() => HardwareScanner.ListAllFans(HardwareMonitor.Instance.ComputerInstance, HardwareMonitor.Instance.SyncLock));
var taskMobo = Task.Run(() => HardwareScanner.ListAllMoboTemps(HardwareMonitor.Instance.ComputerInstance, HardwareMonitor.Instance.SyncLock));

await Task.WhenAll(taskDisks, taskNets, taskGpus, taskFans, taskMobo);
await Task.WhenAll(taskDisks, taskNets, taskGpus, taskCpuTemps, taskFans, taskMobo);

// 2. ★★★ 锁定全局布局 (防止每填一个框就重绘一次) ★★★
this.SuspendLayout();
Expand Down Expand Up @@ -111,10 +112,24 @@ void FillGpuSync(LiteComboBox combo, List<HardwareScanner.GpuOption> data, strin
combo.Inner.EndUpdate();
}

void FillSensorSync(LiteComboBox combo, List<HardwareScanner.SensorOption> data, string currentVal)
{
if (combo == null || combo.Inner.Items.Count > 2) return;

combo.Inner.BeginUpdate();
combo.Inner.Items.Clear();
combo.AddItem(strAuto, "");
foreach (var item in data) combo.AddItem(item.Label, item.Value);

combo.SelectValue(currentVal ?? "");
combo.Inner.EndUpdate();
}

// 3. 瞬间填入所有数据 (因为布局被挂起,用户看不见中间过程)
FillSync(_cbDisk, taskDisks.Result, Config.PreferredDisk);
FillSync(_cbNet, taskNets.Result, Config.PreferredNetwork);
FillGpuSync(_cbGpu, taskGpus.Result, Config.PreferredGpu);
FillSensorSync(_cbCpuTemp, taskCpuTemps.Result, Config.PreferredCpuTemp);
FillSync(_cbMobo, taskMobo.Result, Config.PreferredMoboTemp);

// Fan 的数据是复用的
Expand Down Expand Up @@ -175,6 +190,11 @@ private void CreateSourceCard()
() => Config?.PreferredGpu ?? "",
v => { if (Config != null) Config.PreferredGpu = v ?? ""; });

_cbCpuTemp = (LiteComboBox)group.AddComboPair(this, LanguageManager.T("Menu.CpuTempSource"),
new[] { new { Label = strAuto, Value = "" } },
() => Config?.PreferredCpuTemp ?? "",
v => { if (Config != null) Config.PreferredCpuTemp = v ?? ""; });

_cbMobo = (LiteComboBox)group.AddCombo(this, "Items.MOBO.Temp", new List<string> { strAuto },
() => Config?.PreferredMoboTemp ?? strAuto, v => { if (Config != null) Config.PreferredMoboTemp = (v == strAuto ? "" : v); });

Expand Down