fix(console): 开机自启改为「注册但不启用」,开关切换 enabled

上一版把「关闭」实现成不写登录项。实际在 Windows 上实测 Electron:
  setLoginItemSettings({ openAtLogin: true, enabled: false })
  → openAtLogin=true、launchItems[0].enabled=false、executableWillLaunchAtLogin=false
即登录项已注册(任务管理器「启动」里可见、显示为已禁用)但不会随系统拉起。
所以改成始终注册登录项、只用 enabled 控制是否真正启动,语义与用户要求一致:
  - applyOpenAtLogin / setOpenAtLogin 都走 loginItemSettings(wanted)
  - macOS 无 enabled 参数,仍按注册/注销处理
  - 状态快照的 openAtLogin 以系统实际状态为准(打包后读 executableWillLaunchAtLogin)
  - 文档同步:默认「已注册但未启用」
This commit is contained in:
AskaEth committed 2026-09-10 00:09:49 +08:00
1 parent 1b78c38bb8
commit 0c9a6b6a27
4 files changed
+33 -16

No files matched your search

+1 -1
View File
@@ -39,7 +39,7 @@ const DEFAULTS = {
backgroundColor: '#0b0f1a'
},
startup: {
// 默认不随系统启动;服务管理窗口里有开关,打开后写入登录项
// 默认注册登录项但不启用(任务管理器「启动」里可见);服务管理窗口的开关控制是否真的随系统启动
openAtLogin: false
},
admin: {
+27 -10
View File
@@ -56,6 +56,17 @@ function main() {
return path.join(__dirname, '..', 'config.json')
}
// 开关显示以系统实际状态为准:打包后的 Windows 读登录项 enabled,其余回落配置值。
function openAtLoginEffective() {
const configured = cfg ? cfg.values.startup.openAtLogin === true : false
if (!app.isPackaged || process.platform !== 'win32') return configured
try {
return app.getLoginItemSettings().executableWillLaunchAtLogin === true
} catch {
return configured
}
}
function statusSnapshot() {
const status = service ? service.status : { state: 'stopped', stateLabel: '已停止' }
return {
@@ -64,7 +75,7 @@ function main() {
configWarning: cfg ? cfg.warning : null,
displays: displays ? displays.getInfo() : [],
powerSaveBlocked: powerBlockerId !== null ? powerSaveBlocker.isStarted(powerBlockerId) : false,
openAtLogin: cfg ? cfg.values.startup.openAtLogin === true : false,
openAtLogin: openAtLoginEffective(),
openAtLoginSupported: app.isPackaged && (process.platform === 'win32' || process.platform === 'darwin'),
appVersion: app.getVersion()
}
@@ -295,14 +306,16 @@ function main() {
tray.on('double-click', () => showAdmin())
}
// 开机自启:只对打包后的 Windows/macOS 程序有意义,开发态注册的是 electron 可执行文件
// 开机自启:只对打包后的程序有意义,开发态注册的是 electron 可执行文件。
// Windows 上始终注册登录项(任务管理器「启动」里能看到),用 enabled 控制是否真的拉起:
// 实测 {openAtLogin:true, enabled:false} → openAtLogin=true 且 executableWillLaunchAtLogin=false,
// 即「已注册但未启用」。macOS 没有 enabled 参数,只能注册/注销。
function applyOpenAtLogin() {
if (!app.isPackaged || (process.platform !== 'win32' && process.platform !== 'darwin')) return
// 只有显式 true 才注册;缺省 / null / false 一律不写登录项
const wanted = cfg.values.startup?.openAtLogin === true
try {
app.setLoginItemSettings({ openAtLogin: wanted })
log.push('console', wanted ? '开机自启已启用' : '开机自启已关闭')
app.setLoginItemSettings(loginItemSettings(wanted))
log.push('console', wanted ? '开机自启已启用' : '开机自启已注册但未启用')
} catch (err) {
log.push('console', `设置开机自启失败:${err.message}`)
}
@@ -315,9 +328,13 @@ function main() {
})
}
// 服务管理窗口的「开机自启」开关。Windows 的 Run 项没有「已注册但禁用」的
// 可靠中间态(任务管理器那种禁用走 StartupApproved 私有键,不可靠),
// 所以「不启动」= 不写登录项:打开时写入,关闭时删除。
function loginItemSettings(enabled) {
return process.platform === 'win32'
? { openAtLogin: true, enabled }
: { openAtLogin: enabled }
}
// 服务管理窗口的「开机自启」开关:登录项一直保留,只切换是否真正随系统拉起。
function setOpenAtLogin(enabled) {
if (!cfg) return { ok: false, message: '配置尚未加载' }
const wanted = enabled === true
@@ -334,7 +351,7 @@ function main() {
if (app.isPackaged && (process.platform === 'win32' || process.platform === 'darwin')) {
try {
app.setLoginItemSettings({ openAtLogin: wanted })
app.setLoginItemSettings(loginItemSettings(wanted))
} catch (err) {
// 登录项没写成功,配置也回滚,避免界面与系统状态不一致
cfg.values.startup.openAtLogin = previous
@@ -348,7 +365,7 @@ function main() {
}
}
log.push('console', wanted ? '开机自启已启用' : '开机自启已关闭')
log.push('console', wanted ? '开机自启已启用' : '开机自启已关闭(登录项保留,任务管理器里可见)')
return { ok: true, openAtLogin: wanted }
}