From d6b88d407cda61a8b9ec9ac9bdb167430d43fcfd Mon Sep 17 00:00:00 2001 From: zengql Date: Wed, 20 Aug 2025 20:01:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E6=9D=83=E9=99=90?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=B9=B6=E4=BC=98=E5=8C=96TUN=E4=B8=8E?= =?UTF-8?q?=E8=87=AA=E5=90=AF=E8=81=94=E5=8A=A8=20(#977)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复管理员权限检查不准导致TUN无法开启的问题 - 增加 'fltmc' 命令作为主要判断,'net session' 作为备用,提高在特定环境下的准确性。 2. 优化自启动以自动保持TUN模式开启 - 设置自启动时,根据当前运行身份决定任务权限。 - 为TUN模式提权而重启后,若自启已开启,则自动将计划任务更新为管理员权限。 - 普通权限启动但TUN开启时,主动提示用户需以管理员身份重启。 --- src/main/core/manager.ts | 46 ++++++++++++++----- src/main/sys/autoRun.ts | 7 +-- .../src/components/sider/tun-switcher.tsx | 3 ++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/main/core/manager.ts b/src/main/core/manager.ts index e062bf0..2aa99c8 100644 --- a/src/main/core/manager.ts +++ b/src/main/core/manager.ts @@ -290,13 +290,7 @@ export async function checkTunPermissions(): Promise { try { if (process.platform === 'win32') { - const execPromise = promisify(exec) - try { - await execPromise('net session') - return true - } catch { - return false - } + return await checkAdminPrivileges() } if (process.platform === 'darwin' || process.platform === 'linux') { @@ -341,12 +335,25 @@ export async function checkAdminPrivileges(): Promise { return true } + const execPromise = promisify(exec) + try { - const execPromise = promisify(exec) - await execPromise('net session') + // 首先尝试 fltmc 命令检测管理员权限 + await execPromise('fltmc') + await managerLogger.info('Admin privileges confirmed via fltmc') return true - } catch { - return false + } catch (fltmcError) { + await managerLogger.info('fltmc failed, trying net session as fallback', fltmcError) + + try { + // 如果 fltmc 失败,尝试 net session 命令作为备用检测方法 + await execPromise('net session') + await managerLogger.info('Admin privileges confirmed via net session') + return true + } catch (netSessionError) { + await managerLogger.info('Both fltmc and net session failed, no admin privileges', netSessionError) + return false + } } } @@ -604,6 +611,13 @@ export async function checkAdminRestartForTun(): Promise { const hasAdminPrivileges = await checkAdminPrivileges() if (hasAdminPrivileges) { await patchControledMihomoConfig({ tun: { enable: true }, dns: { enable: true } }) + + const { checkAutoRun, enableAutoRun } = await import('../sys/autoRun') + const autoRunEnabled = await checkAutoRun() + if (autoRunEnabled) { + await enableAutoRun() + } + await restartCore() await managerLogger.info('TUN mode auto-enabled after admin restart') @@ -635,8 +649,16 @@ export async function validateTunPermissionsOnStartup(): Promise { const hasPermissions = await checkMihomoCorePermissions() if (!hasPermissions) { - await managerLogger.warn('TUN is enabled but insufficient permissions detected, auto-disabling TUN...') + await managerLogger.warn( + 'TUN is enabled but insufficient permissions detected, prompting user...' + ) + const confirmed = await showTunPermissionDialog() + if (confirmed) { + await restartAsAdmin() + return + } + await managerLogger.warn('User declined admin restart, auto-disabling TUN...') await patchControledMihomoConfig({ tun: { enable: false } }) const { mainWindow } = await import('../index') diff --git a/src/main/sys/autoRun.ts b/src/main/sys/autoRun.ts index 4c3d55b..654cdd1 100644 --- a/src/main/sys/autoRun.ts +++ b/src/main/sys/autoRun.ts @@ -9,7 +9,8 @@ import { managerLogger } from '../utils/logger' const appName = 'mihomo-party' -function getTaskXml(): string { +function getTaskXml(asAdmin: boolean): string { + const runLevel = asAdmin ? 'HighestAvailable' : 'LeastPrivilege' return ` @@ -21,7 +22,7 @@ function getTaskXml(): string { InteractiveToken - LeastPrivilege + ${runLevel} @@ -83,9 +84,9 @@ export async function enableAutoRun(): Promise { if (process.platform === 'win32') { const execPromise = promisify(exec) const taskFilePath = path.join(tmpdir(), `${appName}.xml`) - await writeFile(taskFilePath, Buffer.from(`\ufeff${getTaskXml()}`, 'utf-16le')) const { checkAdminPrivileges } = await import('../core/manager') const isAdmin = await checkAdminPrivileges() + await writeFile(taskFilePath, Buffer.from(`\ufeff${getTaskXml(isAdmin)}`, 'utf-16le')) if (isAdmin) { await execPromise(`%SystemRoot%\\System32\\schtasks.exe /create /tn "${appName}" /xml "${taskFilePath}" /f`) } else { diff --git a/src/renderer/src/components/sider/tun-switcher.tsx b/src/renderer/src/components/sider/tun-switcher.tsx index 1259dc9..4e95df7 100644 --- a/src/renderer/src/components/sider/tun-switcher.tsx +++ b/src/renderer/src/components/sider/tun-switcher.tsx @@ -75,6 +75,9 @@ const TunSwitcher: React.FC = (props) => { } await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } }) + if (enable && appConfig?.silentStart) { + await window.electron.ipcRenderer.invoke('enableAutoRun') + } } else { await patchControledMihomoConfig({ tun: { enable } }) }