Loading src/WatermarkClock/MainWindow.xaml.cs +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ namespace WatermarkClock _ctx = new Context(); _engine = new TextTemplateEngine { Templates = { new BaseTime(), new BaseFunc(), new HwInfo() } Templates = { new BaseTime(), new BaseFunc(), new HwInfo(), new FileReader() } }; InitComboBox(); Loading src/WatermarkClock/Templates/FileReader.cs 0 → 100644 +80 −0 Original line number Diff line number Diff line using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace WatermarkClock.Templates { public class FileReader : ITextTemplate { private readonly char _flag = '*'; // 匹配 {*...} 整体内容 private readonly Regex _pattern = new Regex(@"\{\*([^}]+)\}", RegexOptions.Compiled); public string Replace(string input) { if (string.IsNullOrEmpty(input)) return input; try { return _pattern.Replace(input, match => { var content = match.Groups[1].Value; var (filePath, lineNumber) = ParsePathAndLine(content); return ReadFileLine(filePath, lineNumber); }); } catch { return input; } } private (string path, int line) ParsePathAndLine(string content) { // 从末尾查找 :数字 作为行号 var colonIndex = content.LastIndexOf(':'); // 检查冒号后面是否全是数字 if (colonIndex > 0 && colonIndex < content.Length - 1) { var afterColon = content.Substring(colonIndex + 1); if (int.TryParse(afterColon, out var lineNum)) { var path = content.Substring(0, colonIndex); return (path, lineNum); } } // 没有行号,默认第1行 return (content, 1); } private string ReadFileLine(string filePath, int lineNumber) { try { if (!File.Exists(filePath)) return $"[文件不存在:{filePath}]"; var lines = File.ReadLines(filePath); var line = lines.Skip(lineNumber - 1).FirstOrDefault(); return line ?? $"[行{lineNumber}超出范围]"; } catch (Exception ex) { return $"[读取错误:{ex.Message}]"; } } public IEnumerable<TemplateVariable> GetVariables() { yield return new TemplateVariable($"{{{_flag}文件路径}}", "读取文件第一行"); yield return new TemplateVariable($"{{{_flag}文件路径:行数}}", "读取文件指定行(从1开始)"); } } } No newline at end of file src/WatermarkClock/Templates/HwInfo.cs +92 −21 Original line number Diff line number Diff line Loading @@ -7,42 +7,113 @@ namespace WatermarkClock.Templates public class HwInfo : ITextTemplate { private PerformanceCounter _systemCpuCounter; private bool _run; private PerformanceCounter _memAvailableCounter; private DateTime _lastGet; private float _lastValue; private float _lastCpuValue; private float _lastMemAvailable; private long _totalPhysicalMemory; public string Replace(string input) public HwInfo() { // 获取物理内存总量(只获取一次) try { using (var searcher = new System.Management.ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem")) { foreach (var obj in searcher.Get()) { _totalPhysicalMemory = Convert.ToInt64(obj["TotalPhysicalMemory"]); break; } } } catch { // 如果 WMI 失败,使用 PerformanceCounter 的方式估算 try { var commitLimit = new PerformanceCounter("Memory", "Commit Limit"); _totalPhysicalMemory = (long)commitLimit.NextValue(); } catch { return input.Replace("{cpu}", GetCpuUsage()); _totalPhysicalMemory = 8L * 1024 * 1024 * 1024; // 默认 8GB } } } private string GetCpuUsage() public string Replace(string input) { if ((DateTime.Now - _lastGet).TotalSeconds > 1) { PerformanceCounter counter; UpdateValues(); } var memUsed = _totalPhysicalMemory - (long)_lastMemAvailable * 1024 * 1024; var memFree = (long)_lastMemAvailable * 1024 * 1024; var memPercent = (float)memUsed / _totalPhysicalMemory * 100; return input .Replace("{cpu}", _lastCpuValue.ToString("F1")) .Replace("{mem}", memPercent.ToString("F1")) .Replace("{mem_used}", FormatBytes(memUsed)) .Replace("{mem_free}", FormatBytes(memFree)) .Replace("{mem_total}", FormatBytes(_totalPhysicalMemory)); } private void UpdateValues() { // CPU try { counter = _systemCpuCounter = _systemCpuCounter ?? _systemCpuCounter = _systemCpuCounter ?? new PerformanceCounter("Processor Information", "% Processor Utility", "_Total"); _lastCpuValue = _systemCpuCounter.NextValue(); } catch (Exception e) catch { counter = _systemCpuCounter = _systemCpuCounter ?? _systemCpuCounter = _systemCpuCounter ?? new PerformanceCounter("Processor", "% Processor Time", "_Total"); _lastCpuValue = _systemCpuCounter.NextValue(); } // 可用内存(MB) try { _memAvailableCounter = _memAvailableCounter ?? new PerformanceCounter("Memory", "Available MBytes"); _lastMemAvailable = _memAvailableCounter.NextValue(); } catch { _lastMemAvailable = 0; } _lastGet = DateTime.Now; return (_lastValue = counter.NextValue()).ToString("F1"); } return _lastValue.ToString("F1"); private string FormatBytes(long bytes) { string[] units = { "B", "KB", "MB", "GB", "TB" }; int unitIndex = 0; double value = bytes; while (value >= 1024 && unitIndex < units.Length - 1) { value /= 1024; unitIndex++; } return $"{value:F1}{units[unitIndex]}"; } public IEnumerable<TemplateVariable> GetVariables() { yield return new TemplateVariable("{cpu}", "中央处理器使用率"); yield return new TemplateVariable("{cpu}", "中央处理器使用率 (%)"); yield return new TemplateVariable("{mem}", "内存使用率 (%)"); yield return new TemplateVariable("{mem_used}", "内存已用空间 (自动单位)"); yield return new TemplateVariable("{mem_free}", "内存剩余空间 (自动单位)"); yield return new TemplateVariable("{mem_total}", "内存总量 (自动单位)"); } } } No newline at end of file src/WatermarkClock/WatermarkClock.csproj +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ <Reference Include="System.Core"/> <Reference Include="System.Data"/> <Reference Include="System.Drawing"/> <Reference Include="System.Management"/> <Reference Include="System.Windows.Forms"/> <Reference Include="System.Xml"/> <Reference Include="System.Xaml"> Loading @@ -85,6 +86,7 @@ <Compile Include="MarkPosition.cs" /> <Compile Include="NotifyIconWrapper.cs" /> <Compile Include="TemplateItem.cs" /> <Compile Include="Templates\FileReader.cs" /> <Compile Include="Templates\HwInfo.cs" /> <Compile Include="TemplateVariable.cs" /> <Compile Include="Templates\BaseFunc.cs" /> Loading Loading
src/WatermarkClock/MainWindow.xaml.cs +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ namespace WatermarkClock _ctx = new Context(); _engine = new TextTemplateEngine { Templates = { new BaseTime(), new BaseFunc(), new HwInfo() } Templates = { new BaseTime(), new BaseFunc(), new HwInfo(), new FileReader() } }; InitComboBox(); Loading
src/WatermarkClock/Templates/FileReader.cs 0 → 100644 +80 −0 Original line number Diff line number Diff line using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace WatermarkClock.Templates { public class FileReader : ITextTemplate { private readonly char _flag = '*'; // 匹配 {*...} 整体内容 private readonly Regex _pattern = new Regex(@"\{\*([^}]+)\}", RegexOptions.Compiled); public string Replace(string input) { if (string.IsNullOrEmpty(input)) return input; try { return _pattern.Replace(input, match => { var content = match.Groups[1].Value; var (filePath, lineNumber) = ParsePathAndLine(content); return ReadFileLine(filePath, lineNumber); }); } catch { return input; } } private (string path, int line) ParsePathAndLine(string content) { // 从末尾查找 :数字 作为行号 var colonIndex = content.LastIndexOf(':'); // 检查冒号后面是否全是数字 if (colonIndex > 0 && colonIndex < content.Length - 1) { var afterColon = content.Substring(colonIndex + 1); if (int.TryParse(afterColon, out var lineNum)) { var path = content.Substring(0, colonIndex); return (path, lineNum); } } // 没有行号,默认第1行 return (content, 1); } private string ReadFileLine(string filePath, int lineNumber) { try { if (!File.Exists(filePath)) return $"[文件不存在:{filePath}]"; var lines = File.ReadLines(filePath); var line = lines.Skip(lineNumber - 1).FirstOrDefault(); return line ?? $"[行{lineNumber}超出范围]"; } catch (Exception ex) { return $"[读取错误:{ex.Message}]"; } } public IEnumerable<TemplateVariable> GetVariables() { yield return new TemplateVariable($"{{{_flag}文件路径}}", "读取文件第一行"); yield return new TemplateVariable($"{{{_flag}文件路径:行数}}", "读取文件指定行(从1开始)"); } } } No newline at end of file
src/WatermarkClock/Templates/HwInfo.cs +92 −21 Original line number Diff line number Diff line Loading @@ -7,42 +7,113 @@ namespace WatermarkClock.Templates public class HwInfo : ITextTemplate { private PerformanceCounter _systemCpuCounter; private bool _run; private PerformanceCounter _memAvailableCounter; private DateTime _lastGet; private float _lastValue; private float _lastCpuValue; private float _lastMemAvailable; private long _totalPhysicalMemory; public string Replace(string input) public HwInfo() { // 获取物理内存总量(只获取一次) try { using (var searcher = new System.Management.ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem")) { foreach (var obj in searcher.Get()) { _totalPhysicalMemory = Convert.ToInt64(obj["TotalPhysicalMemory"]); break; } } } catch { // 如果 WMI 失败,使用 PerformanceCounter 的方式估算 try { var commitLimit = new PerformanceCounter("Memory", "Commit Limit"); _totalPhysicalMemory = (long)commitLimit.NextValue(); } catch { return input.Replace("{cpu}", GetCpuUsage()); _totalPhysicalMemory = 8L * 1024 * 1024 * 1024; // 默认 8GB } } } private string GetCpuUsage() public string Replace(string input) { if ((DateTime.Now - _lastGet).TotalSeconds > 1) { PerformanceCounter counter; UpdateValues(); } var memUsed = _totalPhysicalMemory - (long)_lastMemAvailable * 1024 * 1024; var memFree = (long)_lastMemAvailable * 1024 * 1024; var memPercent = (float)memUsed / _totalPhysicalMemory * 100; return input .Replace("{cpu}", _lastCpuValue.ToString("F1")) .Replace("{mem}", memPercent.ToString("F1")) .Replace("{mem_used}", FormatBytes(memUsed)) .Replace("{mem_free}", FormatBytes(memFree)) .Replace("{mem_total}", FormatBytes(_totalPhysicalMemory)); } private void UpdateValues() { // CPU try { counter = _systemCpuCounter = _systemCpuCounter ?? _systemCpuCounter = _systemCpuCounter ?? new PerformanceCounter("Processor Information", "% Processor Utility", "_Total"); _lastCpuValue = _systemCpuCounter.NextValue(); } catch (Exception e) catch { counter = _systemCpuCounter = _systemCpuCounter ?? _systemCpuCounter = _systemCpuCounter ?? new PerformanceCounter("Processor", "% Processor Time", "_Total"); _lastCpuValue = _systemCpuCounter.NextValue(); } // 可用内存(MB) try { _memAvailableCounter = _memAvailableCounter ?? new PerformanceCounter("Memory", "Available MBytes"); _lastMemAvailable = _memAvailableCounter.NextValue(); } catch { _lastMemAvailable = 0; } _lastGet = DateTime.Now; return (_lastValue = counter.NextValue()).ToString("F1"); } return _lastValue.ToString("F1"); private string FormatBytes(long bytes) { string[] units = { "B", "KB", "MB", "GB", "TB" }; int unitIndex = 0; double value = bytes; while (value >= 1024 && unitIndex < units.Length - 1) { value /= 1024; unitIndex++; } return $"{value:F1}{units[unitIndex]}"; } public IEnumerable<TemplateVariable> GetVariables() { yield return new TemplateVariable("{cpu}", "中央处理器使用率"); yield return new TemplateVariable("{cpu}", "中央处理器使用率 (%)"); yield return new TemplateVariable("{mem}", "内存使用率 (%)"); yield return new TemplateVariable("{mem_used}", "内存已用空间 (自动单位)"); yield return new TemplateVariable("{mem_free}", "内存剩余空间 (自动单位)"); yield return new TemplateVariable("{mem_total}", "内存总量 (自动单位)"); } } } No newline at end of file
src/WatermarkClock/WatermarkClock.csproj +2 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ <Reference Include="System.Core"/> <Reference Include="System.Data"/> <Reference Include="System.Drawing"/> <Reference Include="System.Management"/> <Reference Include="System.Windows.Forms"/> <Reference Include="System.Xml"/> <Reference Include="System.Xaml"> Loading @@ -85,6 +86,7 @@ <Compile Include="MarkPosition.cs" /> <Compile Include="NotifyIconWrapper.cs" /> <Compile Include="TemplateItem.cs" /> <Compile Include="Templates\FileReader.cs" /> <Compile Include="Templates\HwInfo.cs" /> <Compile Include="TemplateVariable.cs" /> <Compile Include="Templates\BaseFunc.cs" /> Loading