Skip to content

Commit 3ac6167

Browse files
committed
fix: switch to WinExe to eliminate console window and add file logger
1 parent 60b1311 commit 3ac6167

7 files changed

Lines changed: 91 additions & 36 deletions

File tree

src/EnergyStarZ/EnergyManager.cs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Text;
66
using System.Runtime.CompilerServices;
77
using EnergyStarZ.Config;
8+
using EnergyStarZ.Utilities;
89
using Microsoft.Extensions.Configuration;
910

1011
namespace EnergyStarZ
@@ -172,7 +173,7 @@ public static void LoadConfiguration()
172173
}
173174
catch (Exception ex)
174175
{
175-
Console.WriteLine($"[ERROR] Failed to load configuration: {ex.Message}");
176+
AppLogger.Error($"Failed to load configuration: {ex.Message}");
176177
}
177178
}
178179

@@ -208,7 +209,7 @@ private void InitializeUnmanagedResources()
208209
}
209210
catch (Exception ex)
210211
{
211-
Console.WriteLine($"[ERROR] Failed to initialize unmanaged resources: {ex.Message}");
212+
AppLogger.Error($"Failed to initialize unmanaged resources: {ex.Message}");
212213
ReleaseUnmanagedResources();
213214
throw;
214215
}
@@ -224,7 +225,7 @@ private void StartTimers()
224225

225226
private static async Task RefreshProcessCacheLoop(CancellationToken cancellationToken)
226227
{
227-
Console.WriteLine($"[{DateTime.UtcNow:O}] Process cache refresh loop started.");
228+
AppLogger.Info("Process cache refresh loop started.");
228229

229230
int consecutiveFailures = 0;
230231
const int maxFailuresBeforeBackoff = 3;
@@ -243,12 +244,12 @@ private static async Task RefreshProcessCacheLoop(CancellationToken cancellation
243244
catch (Exception ex)
244245
{
245246
consecutiveFailures++;
246-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] RefreshProcessCache (failure {consecutiveFailures}): {ex.Message}");
247+
AppLogger.Error($"RefreshProcessCache (failure {consecutiveFailures}): {ex.Message}");
247248

248249
// 连续失败后退避
249250
if (consecutiveFailures >= maxFailuresBeforeBackoff)
250251
{
251-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Too many failures, backing off for {backoffSeconds}s");
252+
AppLogger.Warn($"Too many failures, backing off for {backoffSeconds}s");
252253
await Task.Delay(TimeSpan.FromSeconds(backoffSeconds), cancellationToken);
253254
consecutiveFailures = 0;
254255
continue;
@@ -265,12 +266,12 @@ private static async Task RefreshProcessCacheLoop(CancellationToken cancellation
265266
}
266267
}
267268

268-
Console.WriteLine($"[{DateTime.UtcNow:O}] Process cache refresh loop stopped.");
269+
AppLogger.Info("Process cache refresh loop stopped.");
269270
}
270271

271272
private static async Task PowerStatusCheckLoop(CancellationToken cancellationToken)
272273
{
273-
Console.WriteLine($"[{DateTime.UtcNow:O}] Power status check loop started.");
274+
AppLogger.Info("Power status check loop started.");
274275

275276
while (!cancellationToken.IsCancellationRequested)
276277
{
@@ -280,7 +281,7 @@ private static async Task PowerStatusCheckLoop(CancellationToken cancellationTok
280281
}
281282
catch (Exception ex)
282283
{
283-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] CheckPowerStatus: {ex.Message}");
284+
AppLogger.Error($"CheckPowerStatus: {ex.Message}");
284285
}
285286

286287
try
@@ -293,7 +294,7 @@ private static async Task PowerStatusCheckLoop(CancellationToken cancellationTok
293294
}
294295
}
295296

296-
Console.WriteLine($"[{DateTime.UtcNow:O}] Power status check loop stopped.");
297+
AppLogger.Info("Power status check loop stopped.");
297298
}
298299

299300
private static void CheckPowerStatus()
@@ -319,13 +320,13 @@ private static void CheckPowerStatus()
319320
{
320321
CurrentMode = PowerMode.Auto;
321322
HookManager.SubscribeToWindowEvents();
322-
Console.WriteLine($"[{DateTime.UtcNow:O}] [POWER STATUS] Switched to Battery Mode - Automatic energy saving enabled");
323+
AppLogger.Info("Switched to Battery Mode - Automatic energy saving enabled");
323324
}
324325
else
325326
{
326327
CurrentMode = PowerMode.Paused;
327328
HookManager.UnsubscribeWindowEvents();
328-
Console.WriteLine($"[{DateTime.UtcNow:O}] [POWER STATUS] Switched to AC Mode - Energy saving paused");
329+
AppLogger.Info("Switched to AC Mode - Energy saving paused");
329330
}
330331

331332
_lastSwitchTime = DateTime.UtcNow;
@@ -369,7 +370,7 @@ private void Dispose(bool disposing)
369370
}
370371
catch (Exception ex)
371372
{
372-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARNING] Error waiting for background tasks: {ex.Message}");
373+
AppLogger.Warn($"Error waiting for background tasks: {ex.Message}");
373374
}
374375
finally
375376
{
@@ -509,7 +510,7 @@ private static void AutoAdjustLRUSize(DateTime now)
509510

510511
if (targetSize != _lruCacheSize)
511512
{
512-
Console.WriteLine($"[{now:O}] [LRU] Auto-adjusting LRU size from {_lruCacheSize} to {targetSize} (switches/min: {switchesPerMinute:F1}, active apps: {activeAppCount})");
513+
AppLogger.Info($"Auto-adjusting LRU size from {_lruCacheSize} to {targetSize} (switches/min: {switchesPerMinute:F1}, active apps: {activeAppCount})");
513514
_lruCacheSize = targetSize;
514515

515516
// 如果缩小,淘汰最旧的条目
@@ -570,7 +571,7 @@ private static void ToggleEfficiencyMode(IntPtr hProcess, bool enable)
570571
}
571572
catch (Exception ex)
572573
{
573-
Console.WriteLine($"Error applying efficiency mode to process: {ex.Message}");
574+
AppLogger.Error($"Error applying efficiency mode to process: {ex.Message}");
574575
}
575576
}
576577

@@ -583,7 +584,7 @@ private static void RefreshProcessCache()
583584
}
584585
catch (Exception ex)
585586
{
586-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] Failed to get processes: {ex.Message}");
587+
AppLogger.Error($"Failed to get processes: {ex.Message}");
587588
return;
588589
}
589590

@@ -684,7 +685,7 @@ private static void ApplyEfficiencyMode(IEnumerable<ProcessInfo> processes, uint
684685
}
685686
catch (Exception ex)
686687
{
687-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] ApplyEfficiencyMode failed for {procInfo.Name} (PID: {procInfo.Id}): {ex.Message}");
688+
AppLogger.Error($"ApplyEfficiencyMode failed for {procInfo.Name} (PID: {procInfo.Id}): {ex.Message}");
688689
}
689690
finally
690691
{
@@ -730,7 +731,7 @@ await Task.Run(() =>
730731
}
731732
catch (Exception ex)
732733
{
733-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] RestoreAllProcessesToNormal failed for {procInfo.Name} (PID: {procInfo.Id}): {ex.Message}");
734+
AppLogger.Error($"RestoreAllProcessesToNormal failed for {procInfo.Name} (PID: {procInfo.Id}): {ex.Message}");
734735
}
735736
finally
736737
{
@@ -845,12 +846,12 @@ public static void HandleForegroundEvent(IntPtr hwnd)
845846
AddOrUpdateApp(actualProcId, appName);
846847

847848
// Boost the current foreground app
848-
Console.WriteLine($"[{DateTime.UtcNow:O}] [FOREGROUND] Boost {appName}");
849+
AppLogger.Info($"[FOREGROUND] Boost {appName}");
849850
ToggleEfficiencyMode(actualProcHandle, false);
850851
}
851852
else
852853
{
853-
Console.WriteLine($"[{DateTime.UtcNow:O}] [FOREGROUND] Skip protected process: {appName}");
854+
AppLogger.Info($"[FOREGROUND] Skip protected process: {appName}");
854855
}
855856

856857
// 防抖:距离上次切换太近则跳过
@@ -879,13 +880,13 @@ public static void HandleForegroundEvent(IntPtr hwnd)
879880
var prevAppName = GetProcessNameFromHandle(prevProcHandle);
880881
if (!string.IsNullOrEmpty(prevAppName) && !IsBypassProcess(prevAppName.AsSpan()))
881882
{
882-
Console.WriteLine($"[{DateTime.UtcNow:O}] [BACKGROUND] Throttle {prevAppName}");
883+
AppLogger.Info($"[BACKGROUND] Throttle {prevAppName}");
883884
ToggleEfficiencyMode(prevProcHandle, true);
884885
}
885886
}
886887
catch (Exception ex)
887888
{
888-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] Failed to throttle previous process: {ex.Message}");
889+
AppLogger.Error($"Failed to throttle previous process: {ex.Message}");
889890
}
890891
finally
891892
{

src/EnergyStarZ/EnergyStarZ.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<OutputType Condition="'$(Configuration)'=='ReleaseInvisible'">WinExe</OutputType>
5-
<OutputType Condition="'$(Configuration)'!='ReleaseInvisible'">Exe</OutputType>
4+
<OutputType>WinExe</OutputType>
65
<TargetFramework>net10.0-windows</TargetFramework>
76
<ImplicitUsings>enable</ImplicitUsings>
87
<Nullable>enable</Nullable>

src/EnergyStarZ/HotkeyHandler.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using EnergyStarZ.Utilities;
12
using System;
23
using System.Drawing;
34
using System.Windows.Forms;
@@ -47,21 +48,21 @@ private void RegisterHotkeys()
4748
success = Interop.Win32Api.RegisterHotKey(Handle, HotkeyIdToggleMode, Interop.Win32Api.HotKeyModifiers.Control | Interop.Win32Api.HotKeyModifiers.Alt, (uint)Keys.A);
4849
if (!success)
4950
{
50-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Failed to register hotkey Ctrl+Alt+A (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
51+
AppLogger.Warn($"Failed to register hotkey Ctrl+Alt+A (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
5152
}
5253

5354
// 注册 Ctrl+Alt+P 暂停
5455
success = Interop.Win32Api.RegisterHotKey(Handle, HotkeyIdPause, Interop.Win32Api.HotKeyModifiers.Control | Interop.Win32Api.HotKeyModifiers.Alt, (uint)Keys.P);
5556
if (!success)
5657
{
57-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Failed to register hotkey Ctrl+Alt+P (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
58+
AppLogger.Warn($"Failed to register hotkey Ctrl+Alt+P (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
5859
}
5960

6061
// 注册 Ctrl+Alt+R 恢复
6162
success = Interop.Win32Api.RegisterHotKey(Handle, HotkeyIdResume, Interop.Win32Api.HotKeyModifiers.Control | Interop.Win32Api.HotKeyModifiers.Alt, (uint)Keys.R);
6263
if (!success)
6364
{
64-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Failed to register hotkey Ctrl+Alt+R (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
65+
AppLogger.Warn($"Failed to register hotkey Ctrl+Alt+R (error: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()})");
6566
}
6667
}
6768

src/EnergyStarZ/Interop/HookManager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using EnergyStarZ.Utilities;
12
using System.ComponentModel;
23
using System.Runtime.InteropServices;
34

@@ -62,7 +63,7 @@ public static void WindowEventCallback(IntPtr hWinEventHook, uint eventType,
6263
catch (Exception ex)
6364
{
6465
// 记录异常但不抛出,防止 Windows 移除钩子
65-
Console.WriteLine($"[{DateTime.UtcNow:O}] [ERROR] WindowEventCallback: {ex.Message}");
66+
AppLogger.Error($"WindowEventCallback: {ex.Message}");
6667
}
6768
}
6869

src/EnergyStarZ/Program.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using EnergyStarZ.Interop;
22
using EnergyStarZ.Config;
3+
using EnergyStarZ.Utilities;
34
using Microsoft.Extensions.Configuration;
45
using System.Windows.Forms;
56

@@ -11,7 +12,7 @@ internal class Program
1112

1213
static async Task HouseKeepingThreadProc(AppSettings settings, CancellationToken cancellationToken)
1314
{
14-
Console.WriteLine($"[{DateTime.UtcNow:O}] House keeping thread started.");
15+
AppLogger.Info("House keeping thread started.");
1516

1617
try
1718
{
@@ -34,7 +35,7 @@ static async Task HouseKeepingThreadProc(AppSettings settings, CancellationToken
3435
{
3536
if (settings.EnableLogging)
3637
{
37-
Console.WriteLine($"[{DateTime.UtcNow:O}] Housekeeping error: {ex.Message}");
38+
AppLogger.Error($"Housekeeping error: {ex.Message}");
3839
}
3940
}
4041
}
@@ -58,9 +59,11 @@ static int Main(string[] args)
5859
// In .NET 5.0 and later, System.Environment.OSVersion always returns the actual OS version.
5960
if (Environment.OSVersion.Version.Build < EnergyManager.RequiredWindowsBuild)
6061
{
61-
Console.WriteLine($"E: This program requires Windows 11 24H2 (build {EnergyManager.RequiredWindowsBuild}) or later.");
62-
Console.WriteLine("E: Please upgrade to Windows 11 24H2 for best result, and consider ThinkPad Z13 as your next laptop.");
63-
// ERROR_CALL_NOT_IMPLEMENTED
62+
MessageBox.Show(
63+
$"This program requires Windows 11 24H2 (build {EnergyManager.RequiredWindowsBuild}) or later.\n\nPlease upgrade to Windows 11 24H2 for best result, and consider ThinkPad Z13 as your next laptop.",
64+
"EnergyStarZ - Unsupported OS",
65+
MessageBoxButtons.OK,
66+
MessageBoxIcon.Error);
6467
return EnergyManager.ExitErrorCodeValue;
6568
}
6669

@@ -103,7 +106,7 @@ static int Main(string[] args)
103106
Application.Run(applicationContext);
104107

105108
// 退出时清理资源
106-
Console.WriteLine($"[{DateTime.UtcNow:O}] Application exiting, cleaning up...");
109+
AppLogger.Info("Application exiting, cleaning up...");
107110

108111
// 取消后台任务
109112
cts.Cancel();
@@ -115,7 +118,7 @@ static int Main(string[] args)
115118
}
116119
catch (Exception)
117120
{
118-
Console.WriteLine($"[{DateTime.UtcNow:O}] Housekeeping thread did not respond to cancellation in time.");
121+
AppLogger.Warn("Housekeeping thread did not respond to cancellation in time.");
119122
}
120123

121124
// 取消窗口事件订阅

src/EnergyStarZ/Resources/LocalizationManager.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using EnergyStarZ.Utilities;
12
using System.Globalization;
23
using System.Text.Json;
34

@@ -23,7 +24,7 @@ static LocalizationManager()
2324
catch (Exception ex)
2425
{
2526
// 如果加载失败,使用默认值,避免应用启动时崩溃
26-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Failed to load localization data: {ex.Message}. Using defaults.");
27+
AppLogger.Warn($"Failed to load localization data: {ex.Message}. Using defaults.");
2728
_localizedStrings = new Dictionary<string, Dictionary<string, string>>();
2829
_currentCulture = new CultureInfo("en-US");
2930
}
@@ -129,7 +130,7 @@ private static void SaveCulture(string cultureName)
129130
}
130131
catch (Exception ex)
131132
{
132-
Console.WriteLine($"[{DateTime.UtcNow:O}] [WARN] Failed to save language preference: {ex.Message}");
133+
AppLogger.Warn($"Failed to save language preference: {ex.Message}");
133134
// If saving fails, just continue with the in-memory change
134135
}
135136
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.IO;
3+
using System.Runtime.CompilerServices;
4+
5+
namespace EnergyStarZ.Utilities
6+
{
7+
public static class AppLogger
8+
{
9+
private static readonly string LogFilePath;
10+
private static readonly object _logLock = new();
11+
12+
static AppLogger()
13+
{
14+
var appDir = AppContext.BaseDirectory;
15+
LogFilePath = Path.Combine(appDir, "energy.log");
16+
}
17+
18+
public static void Info(string message)
19+
{
20+
WriteLog("INFO", message);
21+
}
22+
23+
public static void Warn(string message)
24+
{
25+
WriteLog("WARN", message);
26+
}
27+
28+
public static void Error(string message)
29+
{
30+
WriteLog("ERROR", message);
31+
}
32+
33+
private static void WriteLog(string level, string message)
34+
{
35+
lock (_logLock)
36+
{
37+
try
38+
{
39+
var logLine = $"[{DateTime.UtcNow:O}] [{level}] {message}";
40+
File.AppendAllText(LogFilePath, logLine + Environment.NewLine);
41+
}
42+
catch
43+
{
44+
// 如果日志写入失败,静默忽略,防止影响主程序
45+
}
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)