From e35fa316fc3b155b2a130b3ee28ba4d06be41272 Mon Sep 17 00:00:00 2001 From: ezequielnick <107352853+ezequielnick@users.noreply.github.com> Date: Wed, 27 Aug 2025 19:53:21 +0800 Subject: [PATCH] fix: autoupdater admin privileges issue --- src/main/resolve/autoUpdater.ts | 45 +++++++++++++++++-- .../src/components/updater/updater-modal.tsx | 23 +++++----- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/main/resolve/autoUpdater.ts b/src/main/resolve/autoUpdater.ts index ec76880..2b8d7fc 100644 --- a/src/main/resolve/autoUpdater.ts +++ b/src/main/resolve/autoUpdater.ts @@ -9,6 +9,8 @@ import { existsSync } from 'fs' import os from 'os' import { exec, execSync, spawn } from 'child_process' import { promisify } from 'util' +import { appLogger } from '../utils/logger' +import { checkAdminPrivileges } from '../core/manager' export async function checkUpdate(): Promise { const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig() @@ -95,10 +97,45 @@ export async function downloadAndInstallUpdate(version: string): Promise { await writeFile(path.join(dataDir(), file), res.data) } if (file.endsWith('.exe')) { - spawn(path.join(dataDir(), file), ['/S', '--force-run'], { - detached: true, - stdio: 'ignore' - }).unref() + try { + const installerPath = path.join(dataDir(), file) + const isAdmin = await checkAdminPrivileges() + + if (isAdmin) { + await appLogger.info('Running installer with existing admin privileges') + spawn(installerPath, ['/S', '--force-run'], { + detached: true, + stdio: 'ignore' + }).unref() + } else { + // 提升权限安装 + const escapedPath = installerPath.replace(/'/g, "''") + const args = ['/S', '--force-run'] + const argsString = args.map(arg => arg.replace(/'/g, "''")).join("', '") + + const command = `powershell -Command "Start-Process -FilePath '${escapedPath}' -ArgumentList '${argsString}' -Verb RunAs -WindowStyle Hidden"` + + await appLogger.info('Starting installer with elevated privileges') + + const execPromise = promisify(exec) + await execPromise(command, { windowsHide: true }) + + await appLogger.info('Installer started successfully with elevation') + } + } catch (installerError) { + await appLogger.error('Failed to start installer, trying fallback', installerError) + + // Fallback: 尝试使用shell.openPath打开安装包 + try { + await shell.openPath(path.join(dataDir(), file)) + await appLogger.info('Opened installer with shell.openPath as fallback') + } catch (fallbackError) { + await appLogger.error('Fallback method also failed', fallbackError) + const installerErrorMessage = installerError instanceof Error ? installerError.message : String(installerError) + const fallbackErrorMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError) + throw new Error(`Failed to execute installer: ${installerErrorMessage}. Fallback also failed: ${fallbackErrorMessage}`) + } + } } if (file.endsWith('.7z')) { await copyFile(path.join(resourcesFilesDir(), '7za.exe'), path.join(dataDir(), '7za.exe')) diff --git a/src/renderer/src/components/updater/updater-modal.tsx b/src/renderer/src/components/updater/updater-modal.tsx index 64157ee..e31c1a8 100644 --- a/src/renderer/src/components/updater/updater-modal.tsx +++ b/src/renderer/src/components/updater/updater-modal.tsx @@ -55,17 +55,18 @@ const UpdaterModal: React.FC = (props) => { - , - code: ({ children }) => {children}, - h3: ({ ...props }) =>

, - li: ({ children }) =>
  • {children}
  • - }} - > - {changelog} - +