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/Installer/Installer.iss b/Installer/Installer.iss index 622de70..9505e78 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.3.0" +#define MyAppVersion "1.3.1" #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 b72c9fe..3306343 100644 --- a/Installer/ThreadPilot.wxs +++ b/Installer/ThreadPilot.wxs @@ -7,7 +7,7 @@ diff --git a/Installer/setup.iss b/Installer/setup.iss index 25a2870..48135e4 100644 --- a/Installer/setup.iss +++ b/Installer/setup.iss @@ -11,7 +11,7 @@ #endif #ifndef MyAppVersion - #define MyAppVersion "1.3.0" + #define MyAppVersion "1.3.1" #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 index 41967ab..b09572b 100644 --- a/Locales/en-US.xaml +++ b/Locales/en-US.xaml @@ -30,6 +30,12 @@ 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 @@ -94,10 +100,13 @@ 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. @@ -128,6 +137,12 @@ Refresh the current dashboard snapshot Global Power Plan + Process Hotspots + Filter + Memory + Name + Priority + Window Memory Used CPU % Mem % @@ -180,6 +195,7 @@ 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 @@ -206,6 +222,7 @@ Save Configuration No automation rules yet Status: + Automation Monitoring Start Automation Monitoring Stop Automation Monitoring @@ -226,6 +243,7 @@ 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 @@ -276,7 +294,11 @@ 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 @@ -294,6 +316,32 @@ 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 @@ -395,6 +443,46 @@ 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} + 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 @@ -509,7 +597,30 @@ 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? diff --git a/Locales/zh-CN.xaml b/Locales/zh-CN.xaml index 3a9ce20..8f4bcfc 100644 --- a/Locales/zh-CN.xaml +++ b/Locales/zh-CN.xaml @@ -30,6 +30,12 @@ 推荐 不再显示 打开设置 + 主导航 + 权限提升警告覆盖层 + 性能诊断介绍覆盖层 + 启动时最小化建议 + 未保存设置对话框 + 应用启动加载覆盖层 ThreadPilot 活动日志 @@ -94,10 +100,13 @@ 删除选定的掩码 CPU 核心 CPU + 掩码选项 可选性能诊断 诊断是可选的,仅用于故障排除。对于游戏内覆盖层和详细的性能图表,请使用专用工具。 + 诊断是可选的,仅用于故障排除。 + 对于游戏内覆盖层和详细的性能图表,请使用专用工具。 快速提示: 1. 仅在需要针对性的故障排除快照时才打开诊断。 2. 在创建自动化规则之前,仅将热点查看作为提示。 @@ -128,6 +137,12 @@ 刷新当前的仪表板快照 全局电源计划 + 进程热点 + 筛选 + 内存 + 名称 + 优先级 + 窗口 已用内存 CPU % 内存 % @@ -180,6 +195,7 @@ 规则 CPU 掩码: 可选: 选择在该进程启动时要应用的 CPU 掩码 规则优先级 + 更新 可选: 选择在该进程启动时要应用的进程优先级 关联优先级: 当有多个匹配时,优先级较高的关联优先使用 @@ -206,6 +222,7 @@ 保存配置 尚无自动化规则 状态: + 自动化监控 启动自动化监控 停止自动化监控 @@ -226,6 +243,7 @@ 系统进程管理 搜索、过滤和控制活动的进程配置 按名称搜索进程 + 进程搜索 隐藏 Windows 系统进程 隐藏系统进程 隐藏 CPU 使用率极低的进程 @@ -276,6 +294,10 @@ 刷新进程列表 加载更多 加载更多进程 + 刷新进程 + 加载更多进程 + 运行中进程列表 + 支持排序和选择的虚拟化进程表 进程名称 窗口标题 @@ -294,6 +316,32 @@ 应用待处理设置 将待处理的关联性和选定的电源计划应用于选定的进程 ThreadPilot 仅在配置后才应用规则和更改。 + 当前进程状态 + 高级关联性选择器 + 为行上下文菜单关联性操作选择待处理掩码 + 所选电源计划 + 保存为规则 + 无可见窗口标题 + 批次 + 总计) + 优先级 + CPU: 不可用 + 内存: 不可用 + CPU 优先级: 不可用 + 内存优先级不可用 + 关联性: 不可用 + 无已保存规则 + 暂无最近的 ThreadPilot 操作 + 选定进程: {0} (PID {1}) + 当前进程状态: 受保护或访问被拒绝 + 当前进程状态: 已选择 + CPU: {0:N1}% + 内存: {0} + CPU 优先级: {0} + 关联性: 旧版掩码 0x{0:X} + 内存优先级: {0} + 已保存规则 + 存在已保存规则: {0} 高于正常 低于正常 @@ -395,6 +443,46 @@ 导入配置包 保存并应用设置 ThreadPilot + 主题已切换为{0}。 + 无法切换主题为{0}。 + 语言已切换为{0}。 + 无法切换语言。 + 正在保存设置... + 设置已保存但有警告: {0} + 设置已成功保存并应用。 + 保存设置时出错: {0} + 正在重置为默认值... + 设置已重置为默认值(尚未保存) + 重置设置时出错: {0} + 正在导出配置包... + 已取消导出 + 配置已导出到: {0} + 导出设置时出错: {0} + 正在导入配置... + 已取消导入 + 配置包已导入并应用 + 旧版设置已导入(规则未更改) + 导入设置时出错: {0} + 测试通知已发送 + 发送测试通知时出错: {0} + 正在加载设置... + 设置已加载 + 加载设置时出错: {0} + 设置已同步 + 正在检查更新... + 无法确定最新版本。 + 发现新版本: {0} + 应用已是最新版本。已安装版本: {0} + 检查更新时出错: {0} + 设置已被修改 + 设置与已保存的配置一致 + 简体中文 + 英文 + 深色 + 浅色 + 导出 ThreadPilot 配置 + 导入 ThreadPilot 配置 + 无法更新 Windows 自启动。将保留之前的自启动状态。 ThreadPilot 设置 @@ -509,7 +597,30 @@ 游戏加速模式已关闭,持续时间: {0} 进程监控器错误 关联性应用被阻止 + 关联性已应用 + 关联性已调整 + 关联性应用失败 + 关联性错误 优先级应用被阻止 + 优先级警告 + 优先级已应用 + 优先级已调整 + 优先级错误 + 键盘快捷键 + 切换监控快捷键已触发 + 高性能电源计划快捷键已触发 + 刷新进程列表快捷键已触发 + ThreadPilot 已启动 + 进程监控和电源计划管理现已激活 + 启动错误 + 无法启动进程监控管理器 + 自动化监控错误 + 设置已保存 + 应用设置已成功保存 + 设置已保存但有警告 + 设置错误 + 无法保存设置 + 这是一条用于验证您的设置是否正常工作的测试通知。 ThreadPilot 需要管理员权限来管理进程关联性和电源计划。 您想以管理员权限重新启动应用程序吗? 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 @@ - + - - - - - - + + + + + +