diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e973aa..d60d726 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -161,18 +161,13 @@ jobs: schtasks /Delete /TN "ThreadPilot_Startup" /F >nul 2>&1 reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "ThreadPilot" /f >nul 2>&1 - echo [3/4] Optional user data cleanup... - set "REMOVE_DATA=N" - set /p REMOVE_DATA=Do you want to remove user settings at "%APPDATA%\ThreadPilot"? [y/N]: - if /I "%REMOVE_DATA%"=="Y" ( - if exist "%APPDATA%\ThreadPilot" ( - rd /s /q "%APPDATA%\ThreadPilot" - echo User settings removed. - ) else ( - echo No user settings folder found. - ) + echo [3/4] Removing ThreadPilot user data for this Windows account... + rem Full uninstall removes only ThreadPilot-owned per-user AppData. Normal install/update paths never run this script. + if exist "%APPDATA%\ThreadPilot" ( + rd /s /q "%APPDATA%\ThreadPilot" + echo ThreadPilot user data removed. ) else ( - echo User settings were kept. + echo No ThreadPilot user data folder found. ) echo [4/4] Scheduling app folder removal... diff --git a/App.xaml b/App.xaml index 592dae1..58f3c0d 100644 --- a/App.xaml +++ b/App.xaml @@ -10,6 +10,7 @@ + diff --git a/App.xaml.cs b/App.xaml.cs index 9aa438f..06dc022 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -63,50 +63,22 @@ public App() protected override void OnStartup(StartupEventArgs e) { // Parse command line arguments early so special startup modes can short-circuit normal flow. - bool startMinimized = false; - bool isAutostart = false; - bool isSmokeTest = false; - bool registerLaunchTask = false; - bool launchedViaTask = false; -#if DEBUG - bool isTestMode = false; -#endif + var startupMode = StartupMode.Parse(e.Args); bool effectiveStartMinimized = false; ApplicationSettingsModel? loadedSettings = null; - foreach (var arg in e.Args) + effectiveStartMinimized = startupMode.StartMinimized; + + if (startupMode.IsSmokeTest) { - switch (arg.ToLowerInvariant()) - { -#if DEBUG - case "--test": - isTestMode = true; - break; -#endif - case "--smoke-test": - isSmokeTest = true; - break; - case "--start-minimized": - startMinimized = true; - break; - case "--autostart": - isAutostart = true; - break; - case "--startup": // Alternative startup argument - isAutostart = true; - startMinimized = true; - break; - case RegisterLaunchTaskArgument: - registerLaunchTask = true; - break; - case LaunchedViaTaskArgument: - launchedViaTask = true; - break; - } + var smokeLogger = this.ServiceProvider.GetRequiredService>(); + var smokeTestResult = this.RunSmokeTestWithTimeout(smokeLogger, TimeSpan.FromSeconds(10)); + Environment.ExitCode = smokeTestResult; + this.Shutdown(smokeTestResult); + Environment.Exit(smokeTestResult); + return; } - effectiveStartMinimized = startMinimized; - // Set up global exception handlers first AppDomain.CurrentDomain.UnhandledException += this.OnUnhandledException; this.DispatcherUnhandledException += this.OnDispatcherUnhandledException; @@ -130,14 +102,14 @@ protected override void OnStartup(StartupEventArgs e) } else { - if (launchedViaTask) + if (startupMode.LaunchedViaTask) { logger.LogError("Application was launched via managed task marker but is still not elevated."); } #if DEBUG - else if (!isSmokeTest && !isTestMode) + else if (!startupMode.IsTestMode) #else - else if (!isSmokeTest) + else #endif { var launchedElevatedInstance = Task.Run(async () => await elevatedTaskService.TryRunLaunchTaskAsync()).GetAwaiter().GetResult(); @@ -148,7 +120,7 @@ protected override void OnStartup(StartupEventArgs e) return; } - if (!registerLaunchTask) + if (!startupMode.RegisterLaunchTask) { logger.LogInformation("Managed elevated launch task is unavailable. Requesting one-time elevation to bootstrap persistent launch."); var restartInitiated = Task.Run(async () => await elevationService.RestartWithElevation(new[] { RegisterLaunchTaskArgument })).GetAwaiter().GetResult(); @@ -160,9 +132,9 @@ protected override void OnStartup(StartupEventArgs e) } #if DEBUG - if (!isSmokeTest && !isTestMode) + if (!startupMode.IsTestMode) #else - if (!isSmokeTest) + if (true) #endif { logger.LogError("ThreadPilot requires administrator privileges and cannot continue without elevation."); @@ -170,33 +142,28 @@ protected override void OnStartup(StartupEventArgs e) this.Shutdown(1); return; } - - logger.LogWarning("Application is running without administrator privileges in smoke test mode."); } // Enforce single-instance after elevation bootstrap logic to avoid mutex races during handoff. - if (!isSmokeTest) + bool createdNew; + this.singleInstanceMutex = new Mutex(initiallyOwned: true, name: "Global\\ThreadPilot_SingleInstance", createdNew: out createdNew); + if (!createdNew) { - bool createdNew; - this.singleInstanceMutex = new Mutex(initiallyOwned: true, name: "Global\\ThreadPilot_SingleInstance", createdNew: out createdNew); - if (!createdNew) - { - System.Windows.MessageBox.Show( - "ThreadPilot is already running.", - "Instance already open", - MessageBoxButton.OK, - MessageBoxImage.Information); + System.Windows.MessageBox.Show( + "ThreadPilot is already running.", + "Instance already open", + MessageBoxButton.OK, + MessageBoxImage.Information); - this.Shutdown(); - return; - } + this.Shutdown(); + return; } base.OnStartup(e); // Check for test mode #if DEBUG - if (isTestMode) + if (startupMode.IsTestMode) { // Run in console test mode AllocConsole(); @@ -209,22 +176,17 @@ protected override void OnStartup(StartupEventArgs e) } #endif - if (isSmokeTest) - { - var smokeTestResult = Task.Run(async () => await this.RunSmokeTestAsync(logger)).GetAwaiter().GetResult(); - this.Shutdown(smokeTestResult); - return; - } - try { var settingsService = this.ServiceProvider.GetRequiredService(); var themeService = this.ServiceProvider.GetRequiredService(); + var localizationService = this.ServiceProvider.GetRequiredService(); Task.Run(async () => await settingsService.LoadSettingsAsync()).GetAwaiter().GetResult(); var settings = settingsService.Settings; loadedSettings = settings; - effectiveStartMinimized = startMinimized || settings.StartMinimized; + localizationService.ApplyLanguage(settings.Language); + effectiveStartMinimized = startupMode.StartMinimized || settings.StartMinimized; var useDarkTheme = settings.HasUserThemePreference ? settings.UseDarkTheme : themeService.GetSystemUsesDarkTheme(); @@ -256,7 +218,7 @@ protected override void OnStartup(StartupEventArgs e) throw new InvalidOperationException("MainWindow could not be created"); } - var startupWindowBehavior = StartupWindowBehavior.Resolve(isAutostart, effectiveStartMinimized); + var startupWindowBehavior = StartupWindowBehavior.Resolve(startupMode.IsAutostart, effectiveStartMinimized); var showStartupSuggestion = loadedSettings != null && StartupMinimizedSuggestionPolicy.ShouldShow(loadedSettings, startupWindowBehavior); mainWindow.ConfigureStartupMode( @@ -299,16 +261,33 @@ protected override void OnStartup(StartupEventArgs e) } } - private async Task RunSmokeTestAsync(ILogger logger) + private int RunSmokeTestWithTimeout(ILogger logger, TimeSpan timeout) + { + var smokeTestTask = Task.Run(() => this.RunSmokeTest(logger)); + if (smokeTestTask.Wait(timeout)) + { + return smokeTestTask.GetAwaiter().GetResult(); + } + + logger.LogError("ThreadPilot smoke test timed out after {TimeoutSeconds} seconds", timeout.TotalSeconds); + return 2; + } + + private int RunSmokeTest(ILogger logger) { try { logger.LogInformation("Starting ThreadPilot smoke test"); - var settingsService = this.ServiceProvider.GetRequiredService(); - await settingsService.LoadSettingsAsync().ConfigureAwait(false); - _ = this.ServiceProvider.GetRequiredService(); - _ = this.ServiceProvider.GetRequiredService(); + _ = this.ServiceProvider.GetRequiredService(); + _ = this.ServiceProvider.GetRequiredService(); + _ = this.ServiceProvider.GetRequiredService(); + _ = this.ServiceProvider.GetRequiredService(); + + if (!System.IO.Directory.Exists(AppContext.BaseDirectory)) + { + throw new InvalidOperationException("Application base directory was not found."); + } logger.LogInformation("ThreadPilot smoke test completed successfully"); return 0; @@ -320,6 +299,55 @@ private async Task RunSmokeTestAsync(ILogger logger) } } + private readonly struct StartupMode + { + public bool StartMinimized { get; init; } + + public bool IsAutostart { get; init; } + + public bool IsSmokeTest { get; init; } + + public bool RegisterLaunchTask { get; init; } + + public bool LaunchedViaTask { get; init; } + + public bool IsTestMode { get; init; } + + public static StartupMode Parse(IEnumerable args) + { + var mode = default(StartupMode); + foreach (var arg in args) + { + switch (arg.ToLowerInvariant()) + { + case "--test": + mode = mode with { IsTestMode = true }; + break; + case "--smoke-test": + mode = mode with { IsSmokeTest = true }; + break; + case "--start-minimized": + mode = mode with { StartMinimized = true }; + break; + case "--autostart": + mode = mode with { IsAutostart = true }; + break; + case "--startup": + mode = mode with { IsAutostart = true, StartMinimized = true }; + break; + case RegisterLaunchTaskArgument: + mode = mode with { RegisterLaunchTask = true }; + break; + case LaunchedViaTaskArgument: + mode = mode with { LaunchedViaTask = true }; + break; + } + } + + return mode; + } + } + protected override void OnExit(ExitEventArgs e) { AppDomain.CurrentDomain.UnhandledException -= this.OnUnhandledException; diff --git a/Installer/Installer.iss b/Installer/Installer.iss index 8beead0..a17973c 100644 --- a/Installer/Installer.iss +++ b/Installer/Installer.iss @@ -5,7 +5,7 @@ #define MyAppPublisher "ThreadPilot" #define MyAppURL "https://github.com/" #define MyAppExeName "ThreadPilot.exe" -#define MyAppVersion "1.2.0" +#define MyAppVersion "1.4.0" #ifndef MyWizardStyle #define MyWizardStyle "modern dynamic windows11" @@ -20,7 +20,7 @@ AppId={{A2A4C8B5-4A9A-4B1B-93F4-5F8B1C7E8C2A} AppName={#MyAppName} AppVersion={#MyAppVersion} -AppVerName={#MyAppName} {#MyAppVersion} +AppVerName={#MyAppName} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} @@ -54,7 +54,15 @@ Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: de Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent [UninstallRun] -Filename: taskkill.exe; Parameters: "/IM '{#MyAppExeName}' /F"; Flags: runhidden waituntilterminated; RunOnceId: UninstallKill +Filename: "taskkill.exe"; Parameters: "/IM ""{#MyAppExeName}"" /F"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallKill" +Filename: "schtasks.exe"; Parameters: "/Delete /TN ""ThreadPilot_Startup"" /F"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallRemoveThreadPilotStartupTask" +Filename: "reg.exe"; Parameters: "delete ""HKCU\Software\Microsoft\Windows\CurrentVersion\Run"" /v ""ThreadPilot"" /f"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallRemoveThreadPilotRunEntry" + +; ThreadPilot user data is preserved during install/update and removed only when +; the generated uninstaller runs. Per-user AppData cleanup is limited to the +; account context used by uninstall. +[UninstallDelete] +Type: filesandordirs; Name: "{userappdata}\ThreadPilot" [Code] diff --git a/Installer/ThreadPilot.wxs b/Installer/ThreadPilot.wxs index c924f7c..8bcf6f1 100644 --- a/Installer/ThreadPilot.wxs +++ b/Installer/ThreadPilot.wxs @@ -7,7 +7,7 @@ diff --git a/Installer/setup.iss b/Installer/setup.iss index 9cfc206..7fbed61 100644 --- a/Installer/setup.iss +++ b/Installer/setup.iss @@ -11,7 +11,7 @@ #endif #ifndef MyAppVersion - #define MyAppVersion "1.2.0" + #define MyAppVersion "1.4.0" #endif #ifndef MyAppSourceDir @@ -22,7 +22,7 @@ AppId={{E8F7A3B2-5C4D-4E6F-8A9B-1C2D3E4F5A6B} AppName={#MyAppName} AppVersion={#MyAppVersion} -AppVerName={#MyAppName} {#MyAppVersion} +AppVerName={#MyAppName} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL}/issues @@ -62,3 +62,49 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon ; Intentionally do not auto-launch after setup to keep package-manager installs unattended. +; ThreadPilot user data is preserved during install/update. Inno removes installed +; files and shortcuts automatically only when the generated uninstaller runs. +; Per-user AppData cleanup is limited to the account context used by uninstall. +[UninstallRun] +Filename: "taskkill.exe"; Parameters: "/IM ""{#MyAppExeName}"" /F"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallKillThreadPilot" +Filename: "schtasks.exe"; Parameters: "/Delete /TN ""ThreadPilot_Startup"" /F"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallRemoveThreadPilotStartupTask" +Filename: "reg.exe"; Parameters: "delete ""HKCU\Software\Microsoft\Windows\CurrentVersion\Run"" /v ""ThreadPilot"" /f"; Flags: runhidden waituntilterminated; RunOnceId: "UninstallRemoveThreadPilotRunEntry" + +[UninstallDelete] +Type: filesandordirs; Name: "{userappdata}\ThreadPilot" + +[Code] +const + LegacyBetaUninstallKey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{A2A4C8B5-4A9A-4B1B-93F4-5F8B1C7E8C2A}_is1'; + LegacyBetaDisplayName = 'ThreadPilot 0.1.0-beta'; + +function IsLegacyThreadPilotInstallPath(InstallLocation: string): Boolean; +var + NormalizedLocation: string; + ExpectedInstallRoot: string; +begin + NormalizedLocation := Lowercase(RemoveBackslashUnlessRoot(RemoveQuotes(InstallLocation))); + ExpectedInstallRoot := Lowercase(RemoveBackslashUnlessRoot(ExpandConstant('{autopf}\ThreadPilot'))); + Result := (NormalizedLocation = ExpectedInstallRoot); +end; + +procedure DeleteLegacyBetaUninstallEntry(RootKey: Integer); +var + DisplayName: string; + InstallLocation: string; +begin + if RegQueryStringValue(RootKey, LegacyBetaUninstallKey, 'DisplayName', DisplayName) and + RegQueryStringValue(RootKey, LegacyBetaUninstallKey, 'InstallLocation', InstallLocation) and + (DisplayName = LegacyBetaDisplayName) and + IsLegacyThreadPilotInstallPath(InstallLocation) then + begin + RegDeleteKeyIncludingSubkeys(RootKey, LegacyBetaUninstallKey); + end; +end; + +function InitializeSetup(): Boolean; +begin + DeleteLegacyBetaUninstallEntry(HKLM); + DeleteLegacyBetaUninstallEntry(HKCU); + Result := True; +end; diff --git a/Locales/en-US.xaml b/Locales/en-US.xaml new file mode 100644 index 0000000..e2bc6fd --- /dev/null +++ b/Locales/en-US.xaml @@ -0,0 +1,655 @@ + + + + ThreadPilot - Process & Power Plan Manager + Administrator Privileges Recommended + ThreadPilot is running with limited privileges. Some features may not be available. + Administrator access is required for: + • Modifying power plan configurations + • Changing process CPU affinity and priority + • Applying system-level optimizations and tweaks + • Managing protected processes + Continue Without Elevation + Request Elevation + + + Process Management + CPU Masks + Power Plans + Rules + Diagnostics + ThreadPilot Activity + Tweaks + Settings + + + Startup minimized + Enable Startup minimized when you want ThreadPilot to start silently in the tray on future Windows sign-ins. + Recommended + Don't show again + Open Settings + Primary navigation + Elevation warning overlay + Performance introduction overlay + Startup minimized suggestion + Unsaved settings dialog + Application startup loading overlay + + + ThreadPilot Activity + Shows actions performed by ThreadPilot, including applied rules, affinity changes, priority changes, power plan changes, settings changes, tweaks, optimizations, and safe failure messages. + Search: + Category: + Level: + From: + To: + Refresh + Clear Display + Export Activity + Cleanup Diagnostic Files + Open Diagnostic Folder + + + Time + Status + Category + Message + Details + ID + Copy Entry + Refresh + No log entries to display + Adjust filters or refresh logs to load recent ThreadPilot activity. + + + Activity Details + Timestamp: + Status: + Category: + Message: + Details: + Correlation ID: + No log entry selected + Files: + Size: + Debug Diagnostics + Max Size (MB): + Retention (Days): + Save Settings + + + CPU Masks + Create reusable CPU affinity presets for per-process use. + Selecting a mask here only edits the preset. It does not change CPU affinity until you apply it to a process or save it in a process rule. + New + Delete + Duplicate Mask + Mask Information + Name: + Description: + Enabled + Default preset + Pre-selected when ThreadPilot needs a fallback mask or when creating per-process rules. It does not apply CPU affinity automatically. + Disable to temporarily hide this mask + Select CPUs + Toggle CPUs to edit this mask preset. Changes are saved automatically and do not affect running processes. All Cores is the protected default preset. + Mask names, descriptions, CPU selections, and options are saved automatically. + Create a new CPU mask + Delete selected mask + CPUs + CPU + Mask Options + + + Optional Diagnostics + Diagnostics are optional and intended for troubleshooting. For in-game overlays and detailed performance graphs, use dedicated tools. + Diagnostics are optional and intended for troubleshooting. + For in-game overlays and detailed performance graphs, use dedicated tools. + Quick tips: + 1. Open diagnostics only when you need a focused troubleshooting snapshot. + 2. Review hotspots only as a hint before creating automation rules. + 3. Stop live metrics when you are done troubleshooting. + Continue to Diagnostics + + Active Processes + Top CPU and memory consumers with one-click rule creation. + Search processes by name + Rule-backed only + Actionable only + Rule Impact + Create/Update Rule from Selection + Create or update an automation rule from the selected hotspot process + + Stability Timeline + Clear History + Clear the displayed metrics and timeline history + Core Snapshot + Per-core utilization for quick imbalance checks. + Toggle Core Panel + Toggle Process Panel + Start Live Metrics + Start live metrics collection for this dashboard + Stop Live Metrics + Pause live metrics collection; background automation is separate + Refresh + Refresh the current dashboard snapshot + + Global Power Plan + Process Hotspots + Filter + Memory + Name + Priority + Window + Memory Used + CPU % + Mem % + Threads + Events + Severity + Detail + Time + Category + Process + Selected hotspot process + Metrics + Processes + + + Power Plans + Manage the active Windows power plan and import custom .pow profiles + Windows Power Plans + Select the Windows plan to make active. + Set as Active Windows Plan + Change the active Windows power plan to the selected plan + Refresh Plans + Refresh the list of available power plans + Custom Power Plans + Local .pow files ready to import into Windows. + Import Selected .pow + Import the selected custom .pow file into Windows + Add .pow File + Add a new custom power plan file to the custom library + Delete + Active + + + Rules & Automation + Automation monitoring watches process start/stop events and applies configured power plan, CPU mask, and priority rules. + Rule Editor + Create a rule from an executable or running process to automate power plan, CPU mask, and priority behavior. + Executable Match: + Match by Path + Match processes by full path instead of just executable name + Browse for Executable + Click to select an executable file (.exe) from your computer + Choose an executable. Match by path is more precise; matching by name applies to any process with that executable name. + Use Running Process: + Select a currently running process to use its executable + Use Selected Process + Use the executable from the selected running process + Rule Power Plan (global switch): + When this rule matches, Windows switches the global active power plan. + Rule CPU Mask: + Optional: Select a CPU mask to apply when this process starts + Rule Priority + Update + Optional: Select the process priority to apply when this process starts + Association Priority: + Higher priority associations take precedence when multiple match + Add Rule + Update Selected Rule + Update the selected association + Clear Selection + Clear the selected executable + + Current Rules + Define per-process rules. Power plans are global; masks and priorities apply to matching processes. + Remove + Remove the selected association + Default Power Plan (fallback when no rule matches) + Power plan to use when no associated processes are running: + Set Default Power Plan + + Automation Monitoring Settings + Enable Event-Based Automation (WMI) + Enable Automation Fallback Polling + Polling Interval (seconds): + Power Plan Change Delay (ms): + Prevent Duplicate Power Plan Changes + Save Configuration + No automation rules yet + Status: + Automation Monitoring + Start Automation Monitoring + Stop Automation Monitoring + + Applied to each matching process when the automation rule runs. + Applied only to matching processes; it does not change the global Windows power plan. + Selected Executable: + Description: + Automation Service + Rules + Executable + Power Plan + CPU Mask + Priority + Description + Process Priority: + + + Process Management + Search, filter, and control active process configurations + Search processes by name + Process search + Hide Windows system processes + Hide System Processes + Hide processes with very low CPU usage + Hide Idle Processes + Show only applications with visible windows + Active Apps Only + Lock process list + Pause process list refresh and sorting updates while you work with the current list. Background monitoring and saved-rule auto-apply continue while ThreadPilot is running. + Sort by: + Choose how to sort the process list + + Selected Process + No process selected + Select a process from the table to enable affinity, priority, power plan, and rule actions. + Power Plan / Pending Settings + Choose the power plan to activate manually or include with quick apply + Set Power Plan + Activate the selected Windows power plan + + Pending core mask + Select a mask to stage it. This does not change OS affinity until Apply Affinity is clicked. + Apply Affinity + Apply the pending core mask to the selected process and verify the Windows affinity state + Apply Affinity and Save as Rule + Save current process settings as a rule. These settings will be automatically applied when this process starts in the future. + + Set CPU Priority + Apply the selected priority to the process + Enforce Priority by Registry + Apply priority through Windows registry. Process must be restarted for changes to take effect. This setting persists across system reboots. + Set Priority + Realtime priority is blocked by ThreadPilot because it can make Windows unstable or unresponsive. + Realtime (blocked) + + Disable Idle Server + Prevents the system from entering idle state while this process is running. Useful for games and performance-critical applications. + + Profile / Rule + Enter a profile name to save or load settings + Save Profile + Save current CPU affinity and priority as a reusable profile + Load Profile + Load a previously saved profile + Save Current Settings as Rule + + Last ThreadPilot action: + Refresh + Refresh the process list + Load More + Load more processes + Refresh processes + Load more processes + Running process list + Virtualized process table with sorting and selection + + Process Name + Window Title + CPU Usage + Memory Usage + + Affinity staged in the UI. It is not applied until Apply Affinity is clicked. + Affinity currently reported by Windows for the selected process + Read-only preview of current or pending CPU selection + Open CPU Masks tab to create a new custom mask + Shows whether Hyper-Threading (Intel) or SMT (AMD) is present and active on this system + + Copy Process Info + Open Executable Location + Clear CPU Sets + Apply Pending Settings + Apply the pending affinity and selected power plan to the selected process + Rules and changes are applied by ThreadPilot only when configured. + Current process status + Advanced affinity picker + Select the pending mask for row context-menu affinity actions + Selected power plan + Save as Rule + No visible window title + Batch + total) + Priority + CPU: unavailable + Memory: unavailable + CPU priority: unavailable + Memory priority unavailable + Affinity: unavailable + No saved rule + No recent ThreadPilot action + Selected process: {0} (PID {1}) + Current process status: protected or access denied + Current process status: selected + CPU: {0:N1}% + Memory: {0} + CPU priority: {0} + Affinity: legacy mask 0x{0:X} + Memory priority: {0} + saved rule + Saved rule exists: {0} + + Above Normal + Below Normal + High + Idle + Low + Normal + Realtime + Batch + Custom + + Has Window + Window + PID + ID + Memory (MB) + Affinity + Priority + Rules + Name + Set Memory Priority + Very Low + Medium + Refresh Process Info + + + Application Settings + Configure notifications, system tray, and application behavior + Notifications + Enable notifications + Notification Level + All + Warnings/Errors only + Silent + Enable balloon notifications (system tray) + Enable toast notifications (Windows 10+) + Notification Types + Power plan changes + Process monitoring events + Error notifications + Success notifications + Duration (ms): + Test Notification + + System Tray + Show tray icon + Minimize to tray + Close to tray (instead of exit) + Start minimized + Enable pending settings apply from tray + Enable automation monitoring controls from tray + Show detailed tooltips + + Basic Preferences + Autostart + Start with Windows + Automatically start ThreadPilot when Windows starts + Low impact mode in background + Lower ThreadPilot's process priority while minimized or hidden to tray. + + Appearance + Use dark theme + Applies a global Dark/Light theme across all tabs + + Language + 简体中文 (Simplified Chinese) + English (English) + Applies a global display language across the entire application interface. + + Rules & automation + Saved rule auto-apply + Apply saved rules when matching processes start + Applies enabled saved rules while ThreadPilot is running. This does not install a Windows Service and does not use registry/IFEO persistence. + Enable WMI process events + Use Windows Management Instrumentation for process start/stop events + Enable fallback polling + Use polling as backup when WMI process events fail + Polling interval (ms): + Fallback polling (ms): + + Advanced + Enable notification history + Max history items: + Auto-hide notifications + Enable notification sound + Enable debug logging + Enable performance counters + + About + Version: + Copyright © 2026 PrimeBuild + Translator: Ylimhs + License: AGPLv3 + Check for updates + Download and install update + Check automatically on startup + Check interval (days): + Include prerelease updates + Latest version: + Last checked: + Checks on demand using the official GitHub Releases. + + Reset to Defaults + Export Configuration + Import Configuration + Save Settings + ThreadPilot + Theme changed to {0}. + Failed to change theme to {0}. + Language changed to {0}. + Failed to change language. + Saving settings... + Settings saved with warnings: {0} + Settings saved and applied successfully. + Error saving settings: {0} + Resetting to defaults... + Settings reset to defaults (not saved yet) + Error resetting settings: {0} + Exporting configuration bundle... + Export canceled + Configuration exported to: {0} + Error exporting settings: {0} + Importing configuration... + Import canceled + Configuration bundle imported and applied + Legacy settings imported (rules unchanged) + Error importing settings: {0} + Test notification sent + Error sending test notification: {0} + Loading settings... + Settings loaded + Error loading settings: {0} + Settings synchronized + Checking for updates... + Unable to determine the latest version. + New version available: {0} + Application is up to date. Installed version: {0} + Error while checking updates: {0} + Unknown + Not checked + Never + Install ThreadPilot update + ThreadPilot will download and verify version {0}, then ask Windows for permission to run the installer. Continue? + Update canceled. + Downloading and verifying update... + Update installer started. + Update install failed: {0} + Settings have been modified + Settings match the saved configuration + Simplified Chinese + English + Dark + Light + Export ThreadPilot Configuration + Import ThreadPilot Configuration + Failed to update Windows autostart. Keeping previous autostart state. + + + ThreadPilot Settings + Unsaved Settings + You have unsaved changes. Save before closing, discard the changes, or cancel to keep editing. + Cancel + Discard + Save + + + System Tweaks & Optimizations + Configure Windows system optimizations and performance tweaks + Refresh All + Refresh all tweak states + Toggle this Windows tweak + Status + + + Core Parking + Controls CPU core parking for power management + C-States + Controls CPU C-States for power management + SysMain Service + Windows Superfetch/SysMain service for memory management + Prefetch + Windows Prefetch feature for faster application loading + Power Throttling + Windows Power Throttling for energy efficiency + HPET + High Precision Event Timer for system timing + High Scheduling Category + High scheduling priority for gaming applications + Menu Show Delay + Delay before showing context menus + + + Ready + Refreshing system tweaks... + Last refreshed: {0} + Failed to refresh system tweaks + Refresh failed + Toggling {0}... + {0} enabled successfully + {0} disabled successfully + {0} has been enabled + {0} has been disabled + System Tweak Updated + Failed to toggle {0} + Failed to enable {0} + Failed to disable {0} + System Tweak Failed + Failed to {0} {1} + Error toggling {0} + Error toggling {0}: {1} + enable + disable + enabled + disabled + Enabled + Disabled + Not Available + Loading system tweaks... + System tweaks loaded successfully + + + Open Dashboard + Open Diagnostics + Pause Automation Monitoring + Resume Automation Monitoring + System Status + No process selected + Selected: {0} + Apply Pending Settings to Selected Process + Apply Pending Settings to {0} + 🔋 Power Plans + 📋 Profiles + Settings + Exit + No profiles available + Power Plan: {0} + Automation WMI Error + Automation Active + Automation Disabled + Unknown + 💻 CPU: {0:F1}% | RAM: {1:F1}% | {2} + + + Windows denied this change. The process may require administrator rights or may be protected. + The process appears protected by anti-cheat or process protection. ThreadPilot will not try to bypass it. + Administrator mode may help with normal permission issues, but cannot bypass anti-cheat or protected process restrictions. + This CPU selection cannot be safely represented by legacy affinity APIs on this topology. CPU Sets are required for this selection. + This CPU selection does not match the current CPU topology. Review or recreate the preset. + The process exited before ThreadPilot could apply the change. + Windows CPU Sets are unavailable or rejected this selection. ThreadPilot will use a safe fallback only when possible. + High priority can improve responsiveness for some workloads but may reduce system responsiveness. + Realtime priority is blocked by ThreadPilot because it can make Windows unstable or unresponsive. + Persistent launch-time priority may be supported for normal processes, but it does not bypass protected process or anti-cheat restrictions. + Applies saved rules when a matching process starts. Some protected or anti-cheat processes may reject changes. Administrator mode can help with normal permission issues but cannot bypass protection. + The process appears protected by anti-cheat or process protection. ThreadPilot will not try to override it. + + + Power Plan Changed + Power plan changed from '{0}' to '{1}' + Power plan changed to '{0}' for process '{1}' + Process Monitoring Enabled + Process Monitoring Disabled + CPU Affinity Applied + CPU affinity set for '{0}': {1} + Game Boost Activated + Game Boost mode activated for {0} + Game Boost Deactivated + Game Boost mode deactivated after {0} + Process Monitor Error + Affinity blocked + Affinity applied + Affinity adjusted + Affinity failed + Affinity error + Priority blocked + Priority warning + Priority applied + Priority adjusted + Priority error + Keyboard Shortcut + Toggle monitoring shortcut activated + High Performance power plan shortcut activated + Refresh process list shortcut activated + ThreadPilot Started + Process monitoring and power plan management is now active + Startup Error + Failed to start process monitoring manager + Automation Monitoring Error + Settings Saved + Application settings have been saved successfully + Settings Saved with Warnings + Settings Error + Failed to save settings + This is a test notification to verify your settings are working correctly. + + + ThreadPilot requires administrator privileges to manage process affinity and power plans. Would you like to restart the application with administrator privileges? + Administrator Privileges Required + Failed to restart with administrator privileges. Please manually run ThreadPilot as administrator. + Elevation Failed + Running with Administrator privileges + Running with limited privileges + + + Could not query Core Parking value via powercfg + Could not query C-States value via powercfg + Prefetch registry key not found + Power Throttling not available on this system + PriorityControl registry key not found + Desktop registry key not found + diff --git a/Locales/zh-CN.xaml b/Locales/zh-CN.xaml new file mode 100644 index 0000000..d3cc1fa --- /dev/null +++ b/Locales/zh-CN.xaml @@ -0,0 +1,655 @@ + + + + ThreadPilot - 进程与电源计划管理器 + 推荐以管理员权限运行 + ThreadPilot 当前正以受限权限运行。某些功能可能无法使用。 + 需要管理员访问权限以执行以下操作: + • 修改电源计划配置 + • 更改进程 CPU 关联性和优先级 + • 应用系统级优化和调整 + • 管理受保护的进程 + 不提升权限继续 + 请求权限提升 + + + 进程管理 + CPU 掩码 + 电源计划 + 自动化规则 + 性能诊断 + 活动日志 + 系统微调 + 应用设置 + + + 启动时最小化 + 开启此项后,ThreadPilot 会在 Windows 登录时静默启动至系统托盘。 + 推荐 + 不再显示 + 打开设置 + 主导航 + 权限提升警告覆盖层 + 性能诊断介绍覆盖层 + 启动时最小化建议 + 未保存设置对话框 + 应用启动加载覆盖层 + + + ThreadPilot 活动日志 + 显示 ThreadPilot 执行的操作,包括已应用规则、关联性更改、优先级更改、电源计划更改、设置更改、调整、优化以及安全故障消息。 + 搜索: + 类别: + 级别: + 从: + 至: + 刷新 + 清除显示 + 导出活动 + 清理诊断文件 + 打开诊断文件夹 + + + 时间 + 状态 + 类别 + 消息 + 详情 + ID + 复制条目 + 刷新 + 没有要显示的日志条目 + 调整过滤器或刷新日志以加载最近的 ThreadPilot 活动。 + + + 活动详情 + 时间戳: + 状态: + 类别: + 消息: + 详情: + 相关性 ID: + 未选择日志条目 + 文件: + 大小: + 调试诊断 + 最大大小 (MB): + 保留天数 (天): + 保存设置 + + + CPU 掩码 + 创建可复用的 CPU 关联性预设以供每个进程使用。 + 在此处选择掩码仅编辑预设。在将其应用于进程或保存在进程规则中之前,它不会更改 CPU 关联性。 + 新建 + 删除 + 复制掩码 + 掩码信息 + 名称: + 描述: + 已启用 + 默认预设 + 当 ThreadPilot 需要后备掩码或创建针对每个进程的规则时预先选择。它不会自动应用 CPU 关联性。 + 禁用以暂时隐藏此掩码 + 选择 CPU 核心 + 切换 CPU 以编辑此掩码预设。更改将自动保存,且不会影响正在运行的进程。“所有核心”是受保护的默认预设。 + 掩码名称、描述、CPU 选择和选项会自动保存。 + 创建新的 CPU 掩码 + 删除选定的掩码 + CPU 核心 + CPU + 掩码选项 + + + 可选性能诊断 + 诊断是可选的,仅用于故障排除。对于游戏内覆盖层和详细的性能图表,请使用专用工具。 + 诊断是可选的,仅用于故障排除。 + 对于游戏内覆盖层和详细的性能图表,请使用专用工具。 + 快速提示: + 1. 仅在需要针对性的故障排除快照时才打开诊断。 + 2. 在创建自动化规则之前,仅将热点查看作为提示。 + 3. 故障排除完成后,停止实时指标收集。 + 继续前往诊断 + + 活动进程 + 通过一键规则创建来监控 CPU 和内存的占用大户。 + 按名称搜索进程 + 仅限包含规则的 + 仅限可操作的 + 规则影响 + 基于选择创建/更新规则 + 为选定的热点进程创建或更新自动化规则 + + 稳定性时间线 + 清除历史记录 + 清除显示的指标和时间轴历史记录 + 核心快照 + 单核利用率,用于快速的不平衡检查。 + 切换核心面板 + 切换进程面板 + 开始实时指标 + 为此控制面板启动实时指标收集 + 停止实时指标 + 暂停实时指标收集;后台自动化会单独运行 + 刷新 + 刷新当前的仪表板快照 + + 全局电源计划 + 进程热点 + 筛选 + 内存 + 名称 + 优先级 + 窗口 + 已用内存 + CPU % + 内存 % + 线程数 + 事件 + 严重性 + 详情 + 时间 + 类别 + 进程 + 选定的热点进程 + 指标 + 进程 + + + 电源计划管理 + 管理活动的 Windows 电源计划并导入自定义 .pow 配置文件 + Windows 电源计划 + 选择要激活的 Windows 电源计划。 + 设为活动 Windows 电源计划 + 将活动的 Windows 电源计划更改为所选计划 + 刷新计划 + 刷新可用电源计划的列表 + 自定义电源计划 + 已准备好导入 Windows 的本地 .pow 文件。 + 导入选中的 .pow + 将所选的自定义 .pow 文件导入 Windows + 添加 .pow 文件 + 向自定义库添加新的自定义电源计划文件 + 删除 + 活动 + + + 规则与自动化 + 自动化监控监视进程的启动/停止事件,并应用配置的电源计划、CPU 掩码和优先级规则。 + 规则编辑器 + 从可执行文件或运行中的进程创建规则,以实现电源计划、CPU 掩码和优先级行为的自动化。 + 可执行文件匹配: + 按路径匹配 + 按完整路径而不是仅按可执行文件名称匹配进程 + 浏览可执行文件 + 点击以从您的计算机选择可执行文件 (.exe) + 选择可执行文件。按路径匹配更精确;按名称匹配适用于任何具有该可执行文件名称的进程。 + 使用运行中的进程: + 选择当前运行的进程以使用其可执行文件 + 使用所选进程 + 使用所选运行中进程的可执行文件 + 规则电源计划 (全局切换): + 当此规则匹配时,Windows 将切换全局活动电源计划。 + 规则 CPU 掩码: + 可选: 选择在该进程启动时要应用的 CPU 掩码 + 规则优先级 + 更新 + 可选: 选择在该进程启动时要应用的进程优先级 + 关联优先级: + 当有多个匹配时,优先级较高的关联优先使用 + 添加规则 + 更新选定规则 + 更新所选的关联 + 清除选择 + 清除选定的可执行文件 + + 当前规则 + 定义针对每个进程的规则。电源计划是全局的;掩码和优先级适用于匹配的进程。 + 删除 + 删除所选关联 + 默认电源计划 (当无规则匹配时的后备方案) + 当没有关联的进程在运行时要使用的电源计划: + 设置默认电源计划 + + 自动化监控设置 + 启用基于事件的自动化 (WMI) + 启用自动化后备轮询 + 轮询间隔 (秒): + 电源计划切换延迟 (毫秒): + 防止重复更改电源计划 + 保存配置 + 尚无自动化规则 + 状态: + 自动化监控 + 启动自动化监控 + 停止自动化监控 + + 在运行自动化规则时应用于每个匹配的进程。 + 仅应用于匹配的进程;它不会更改全局 Windows 电源计划。 + 选定的可执行文件: + 描述: + 自动化服务 + 规则 + 可执行文件 + 电源计划 + CPU 掩码 + 优先级 + 描述 + 进程优先级: + + + 系统进程管理 + 搜索、过滤和控制活动的进程配置 + 按名称搜索进程 + 进程搜索 + 隐藏 Windows 系统进程 + 隐藏系统进程 + 隐藏 CPU 使用率极低的进程 + 隐藏空闲进程 + 仅显示具有可见窗口的应用程序 + 仅限活动应用 + 锁定进程列表 + 在您处理当前列表时暂停进程列表刷新和排序更新。ThreadPilot 运行时,后台监控和保存的规则自动应用仍将继续。 + 排序方式: + 选择如何对进程列表进行排序 + + 选定的进程 + 未选择进程 + 从表格中选择一个进程以启用关联性、优先级、电源计划和规则操作。 + 电源计划 / 待处理设置 + 选择要手动激活的电源计划,或包含在快速应用中 + 设置电源计划 + 激活所选的 Windows 电源计划 + + 待处理的核心掩码 + 选择一个掩码来暂存它。在点击“应用关联性”之前,这不会更改操作系统关联性。 + 应用关联性 + 将待处理的核心掩码应用于选定的进程,并验证 Windows 关联性状态 + 应用关联性并保存为规则 + 将当前进程设置保存为规则。以后此进程启动时将自动应用这些设置。 + + 设置 CPU 优先级 + 将所选优先级应用于进程 + 通过注册表强制执行优先级 + 通过 Windows 注册表应用优先级。必须重新启动进程才能使更改生效。此设置在系统重启后仍然有效。 + 设置优先级 + 实时优先级已被 ThreadPilot 阻止,因为它可能会使 Windows 不稳定或无响应。 + 实时 (已阻止) + + 禁用空闲服务 + 在此进程运行时阻止系统进入空闲状态。适用于游戏和对性能要求严苛的应用程序。 + + 配置文件 / 规则 + 输入配置文件名称以保存或加载设置 + 保存配置文件 + 将当前 CPU 关联性和优先级保存为可复用的配置文件 + 加载配置文件 + 加载以前保存的配置文件 + 保存当前设置为规则 + + 最后一次 ThreadPilot 操作: + 刷新 + 刷新进程列表 + 加载更多 + 加载更多进程 + 刷新进程 + 加载更多进程 + 运行中进程列表 + 支持排序和选择的虚拟化进程表 + + 进程名称 + 窗口标题 + CPU 使用率 + 内存使用 + + 关联性已暂存在 UI 中。在点击“应用关联性”之前不会应用。 + Windows 当前报告的所选进程的关联性 + 当前或待处理 CPU 选择的只读预览 + 打开 CPU 掩码选项卡以创建新的自定义掩码 + 显示此系统上是否具有并启用了超线程 (Intel) 或 SMT (AMD) + + 复制进程信息 + 打开可执行文件位置 + 清除 CPU 集 + 应用待处理设置 + 将待处理的关联性和选定的电源计划应用于选定的进程 + ThreadPilot 仅在配置后才应用规则和更改。 + 当前进程状态 + 高级关联性选择器 + 为行上下文菜单关联性操作选择待处理掩码 + 所选电源计划 + 保存为规则 + 无可见窗口标题 + 批次 + 总计) + 优先级 + CPU: 不可用 + 内存: 不可用 + CPU 优先级: 不可用 + 内存优先级不可用 + 关联性: 不可用 + 无已保存规则 + 暂无最近的 ThreadPilot 操作 + 选定进程: {0} (PID {1}) + 当前进程状态: 受保护或访问被拒绝 + 当前进程状态: 已选择 + CPU: {0:N1}% + 内存: {0} + CPU 优先级: {0} + 关联性: 旧版掩码 0x{0:X} + 内存优先级: {0} + 已保存规则 + 存在已保存规则: {0} + + 高于正常 + 低于正常 + + 空闲 + + 正常 + 实时 + 批处理 + 自定义 + + 有窗口 + 窗口 + PID + ID + 内存 (MB) + 关联性 + 优先级 + 规则 + 名称 + 设置内存优先级 + 极低 + + 刷新进程信息 + + + ThreadPilot 系统设置 + 配置通知、系统托盘和应用程序行为 + 系统通知 + 启用应用通知 + 通知级别 + 全部显示 + 仅警告与错误 + 静音模式 + 启用系统托盘气泡通知 + 启用 Windows 吐司通知 (Windows 10+) + 通知事件类别 + 电源计划变更 + 进程监控事件 + 错误与异常通知 + 操作成功提示 + 持续显示时间 (毫秒): + 测试通知发送 + + 系统托盘栏 + 显示托盘图标 + 最小化到托盘 + 关闭主窗口时最小化到托盘 + 开机启动时最小化 + 允许从托盘菜单应用待处理设置 + 允许从托盘菜单控制自动化监控 + 托盘图标显示详细鼠标提示 + + 基本偏好设置 + 系统开机启动 + 随 Windows 开机启动 + 在 Windows 系统启动时自动开启 ThreadPilot + 后台低系统影响模式 + 在最小化或隐藏至托盘时自动降低 ThreadPilot 的进程优先级。 + + 外观主题 + 启用暗黑主题 + 在所有选项卡上全局应用 亮色/暗色 视觉风格 + + 显示语言 + 简体中文 (Simplified Chinese) + English (English) + 在整个应用程序界面应用全局的语言设置。 + + 规则与自动化 + 保存规则自动应用 + 在匹配的进程启动时自动应用已保存规则 + 在 ThreadPilot 运行时自动应用已启用的保存规则。这不会注册 Windows 服务,也不使用注册表/IFEO 进行常驻。 + 启用 WMI 进程启动监控 + 使用 Windows Management Instrumentation 来监听进程启动/退出事件 + 启用后备轮询监控 + 如果 WMI 进程事件订阅失败,自动启用定时轮询作为备份 + 轮询间隔时间 (毫秒): + 后备轮询间隔时间 (毫秒): + + 高级与调试设置 + 启用通知历史记录 + 最大历史条目数: + 自动渐隐通知气泡 + 播放提示音 + 开启调试诊断日志记录 + 启用内部性能计数器 + + 关于应用 + 软件版本: + 版权所有 © 2026 PrimeBuild + 翻译人员:Ylimhs + 软件授权: AGPLv3 + 检查新版本 + 下载并安装更新 + 启动时自动检查更新 + 检查间隔(天): + 包含预发布版本 + 最新版本: + 上次检查: + 按需通过官方 GitHub Releases API 检索最新稳定版本。 + + 重置为默认值 + 导出配置包 + 导入配置包 + 保存并应用设置 + ThreadPilot + 主题已切换为{0}。 + 无法切换主题为{0}。 + 语言已切换为{0}。 + 无法切换语言。 + 正在保存设置... + 设置已保存但有警告: {0} + 设置已成功保存并应用。 + 保存设置时出错: {0} + 正在重置为默认值... + 设置已重置为默认值(尚未保存) + 重置设置时出错: {0} + 正在导出配置包... + 已取消导出 + 配置已导出到: {0} + 导出设置时出错: {0} + 正在导入配置... + 已取消导入 + 配置包已导入并应用 + 旧版设置已导入(规则未更改) + 导入设置时出错: {0} + 测试通知已发送 + 发送测试通知时出错: {0} + 正在加载设置... + 设置已加载 + 加载设置时出错: {0} + 设置已同步 + 正在检查更新... + 无法确定最新版本。 + 发现新版本: {0} + 应用已是最新版本。已安装版本: {0} + 检查更新时出错: {0} + 未知 + 尚未检查 + 从未检查 + 安装 ThreadPilot 更新 + ThreadPilot 将下载并验证版本 {0},然后请求 Windows 权限运行安装程序。是否继续? + 更新已取消。 + 正在下载并验证更新... + 更新安装程序已启动。 + 更新安装失败: {0} + 设置已被修改 + 设置与已保存的配置一致 + 简体中文 + 英文 + 深色 + 浅色 + 导出 ThreadPilot 配置 + 导入 ThreadPilot 配置 + 无法更新 Windows 自启动。将保留之前的自启动状态。 + + + ThreadPilot 设置 + 未保存的设置 + 您有尚未保存的更改。请选择在关闭前保存、放弃修改或取消并返回编辑。 + 取消 + 放弃更改 + 保存 + + + 系统微调与优化 + 配置 Windows 系统级优化项和性能微调选项 + 刷新状态 + 刷新所有微调选项的状态 + 切换此 Windows 系统微调项 + 当前状态 + + + 核心休眠 (Core Parking) + 控制 CPU 核心休眠以进行电源管理 + C-States 状态 + 控制 CPU C-States 以进行节能电源管理 + SysMain 服务 + Windows Superfetch/SysMain 服务,用于内存管理 + 预取 (Prefetch) + Windows Prefetch 功能,用于加速应用程序加载 + 电源限流 (Power Throttling) + Windows 电源限流功能,用于能效优化 + HPET 定时器 + 高精度事件计时器,用于系统精准定时 + 高调度优先级类别 + 为游戏应用程序提供高调度优先级 + 菜单显示延迟 + 显示上下文菜单之前的延迟时间 + + + 就绪 + 正在刷新系统微调选项... + 上次刷新时间: {0} + 刷新系统微调失败 + 刷新失败 + 正在切换 {0}... + {0} 已成功启用 + {0} 已成功禁用 + {0} 已启用 + {0} 已禁用 + 系统微调已更新 + 无法切换 {0} + 未能启用 {0} + 未能禁用 {0} + 系统微调失败 + 未能{0}{1} + 切换 {0} 出错 + 切换 {0} 时出错: {1} + 启用 + 禁用 + 启用 + 禁用 + 已启用 + 已禁用 + 不可用 + 正在加载系统微调... + 系统微调已成功加载 + + + 打开主控制面板 + 打开性能诊断 + 暂停自动化监控 + 恢复自动化监控 + 系统状态 + 未选择进程 + 已选择: {0} + 应用待处理设置到所选进程 + 应用待处理设置到 {0} + 🔋 电源计划 + 📋 配置文件 + 应用设置 + 退出程序 + 无可用配置文件 + 电源计划: {0} + 自动化 WMI 错误 + 自动化监控已启用 + 自动化监控已禁用 + 未知 + 💻 CPU: {0:F1}% | 内存: {1:F1}% | {2} + + + Windows 拒绝了此更改。该进程可能需要管理员权限或受保护。 + 该进程似乎受到反作弊系统或进程保护的保护。ThreadPilot 不会尝试绕过它。 + 管理员模式可能有助于解决普通的权限问题,但无法绕过反作弊系统或受保护的进程限制。 + 在此拓扑上,此 CPU 选择无法由传统关联性 API 安全地表示。此选择需要使用 CPU 集。 + 此 CPU 选择与当前 CPU 拓扑不匹配。请检查或重新创建预设。 + 在 ThreadPilot 应用更改之前,进程已退出。 + Windows CPU 集不可用或拒绝了此选择。ThreadPilot 将仅在可能时使用 safe 后备方案。 + 高优先级可以提高某些工作负载的响应速度,但可能会降低系统整体响应速度。 + 实时优先级已被 ThreadPilot 阻止,因为它可能会使 Windows 不稳定或无响应。 + 普通进程可能支持持久的启动时优先级,但这不会绕过受保护进程或反作弊系统的限制。 + 在匹配的进程启动时应用保存的规则。某些受保护或反作弊进程可能会拒绝更改。管理员模式有助于解决普通权限问题,但无法绕过进程保护。 + 该进程似乎受到反作弊系统或进程保护的保护。ThreadPilot 不会尝试对其进行改写。 + + + 电源计划已更改 + 电源计划已从“{0}”更改为“{1}” + 已为进程“{1}”将电源计划切换为“{0}” + 进程监控已启用 + 进程监控已禁用 + CPU 关联性已应用 + 已为“{0}”设置 CPU 关联性: {1} + 游戏加速已启用 + 已为 {0} 启用游戏加速模式 + 游戏加速已关闭 + 游戏加速模式已关闭,持续时间: {0} + 进程监控器错误 + 关联性应用被阻止 + 关联性已应用 + 关联性已调整 + 关联性应用失败 + 关联性错误 + 优先级应用被阻止 + 优先级警告 + 优先级已应用 + 优先级已调整 + 优先级错误 + 键盘快捷键 + 切换监控快捷键已触发 + 高性能电源计划快捷键已触发 + 刷新进程列表快捷键已触发 + ThreadPilot 已启动 + 进程监控和电源计划管理现已激活 + 启动错误 + 无法启动进程监控管理器 + 自动化监控错误 + 设置已保存 + 应用设置已成功保存 + 设置已保存但有警告 + 设置错误 + 无法保存设置 + 这是一条用于验证您的设置是否正常工作的测试通知。 + + + ThreadPilot 需要管理员权限来管理进程关联性和电源计划。 您想以管理员权限重新启动应用程序吗? + 需要管理员权限 + 无法以管理员权限重新启动。请手动以管理员身份运行 ThreadPilot。 + 权限提升失败 + 以管理员权限运行中 + 以受限权限运行中 + + + 无法通过 powercfg 查询核心停车值 + 无法通过 powercfg 查询 C-States 值 + 未找到预取注册表键 + 此系统上不支持电源限流 + 未找到 PriorityControl 注册表键 + 未找到 Desktop 注册表键 + diff --git a/MainWindow.Behaviors.partial.cs b/MainWindow.Behaviors.partial.cs index a4da578..1c857ee 100644 --- a/MainWindow.Behaviors.partial.cs +++ b/MainWindow.Behaviors.partial.cs @@ -157,27 +157,26 @@ private async Task CheckForUpdatesAtStartupAsync() try { this.LogDebug("Startup update check started"); - var checker = this.serviceProvider.GetRequiredService(); - var currentVersion = GetCurrentApplicationVersion(); - var (latest, _) = await checker.GetLatestVersionAsync("PrimeBuild-pc", "ThreadPilot"); + var updateService = this.serviceProvider.GetRequiredService(); + var result = await updateService.CheckForUpdatesAsync(new UpdateCheckRequest(UpdateCheckTrigger.Startup)); - if (latest == null) + if (result.Status == UpdateCheckStatus.Skipped) { - this.LogDebug("Startup update check completed without release information"); + this.LogDebug($"Startup update check skipped: {result.Message}"); return; } - if (latest <= currentVersion) + if (!result.IsUpdateAvailable || result.Release == null) { - this.LogDebug($"Startup update check complete: installed {currentVersion}, latest {latest}"); + this.LogDebug($"Startup update check complete: {result.Message}"); return; } await this.notificationService.ShowNotificationAsync( "Update available", - $"ThreadPilot {latest} is available from GitHub releases.", + $"ThreadPilot {result.Release.Version} is available. Open Settings to download and install it.", NotificationType.Information); - this.LogDebug($"Startup update check found update: installed {currentVersion}, latest {latest}"); + this.LogDebug($"Startup update check found update: installed {result.CurrentVersion}, latest {result.Release.Version}"); } catch (Exception ex) { diff --git a/MainWindow.xaml b/MainWindow.xaml index 7a203ed..c991768 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -10,7 +10,7 @@ mc:Ignorable="d" ExtendsContentIntoTitleBar="True" WindowBackdropType="Mica" - Title="ThreadPilot - Process & Power Plan Manager" + Title="{DynamicResource MainWindow_Title}" Height="864" Width="1280" WindowStartupLocation="CenterScreen" @@ -86,7 +86,7 @@ IsPaneOpen="False" OpenPaneLength="180" CompactPaneLength="52" - AutomationProperties.Name="Primary navigation"> + AutomationProperties.Name="{DynamicResource MainWindow_PrimaryNavigation}"> - - - + @@ -290,22 +290,22 @@ - + - + - + - + - - + - - + - + @@ -168,9 +168,9 @@ - + - - + @@ -219,20 +219,20 @@ - + - @@ -583,7 +583,7 @@ CornerRadius="8"> - @@ -595,7 +595,7 @@ Background="{DynamicResource QuietRowBackgroundBrush}" Margin="0,0,0,12"> - @@ -610,7 +610,7 @@ - - + - + + ToolTip="{DynamicResource ProcessView_AffinityCurrentTooltip}"/> + ToolTip="{DynamicResource ProcessView_AffinityStagedTooltip}"/> - + + ToolTip="{DynamicResource ProcessView_StageMaskTooltip}"> @@ -700,7 +700,7 @@ FontSize="{StaticResource ProcessFontSmall}" Margin="0,2,0,6" Foreground="{Binding IsHyperThreadingActive, Converter={StaticResource BoolToColorConverter}}" - ToolTip="Shows whether Hyper-Threading (Intel) or SMT (AMD) is present and active on this system"/> + ToolTip="{DynamicResource ProcessView_HyperThreadingTooltip}"/> + ToolTip="{DynamicResource ProcessView_CpuSelectionPreviewTooltip}"/> @@ -736,59 +736,59 @@ - + - - - - - - + + + + + +