From fa9328b5780b4df68bf58873c0b29ac4037bb90a Mon Sep 17 00:00:00 2001 From: pompurin404 Date: Sat, 24 Aug 2024 17:40:01 +0800 Subject: [PATCH] Avoid UAC pop-up --- changelog.md | 1 + electron-builder.yml | 1 - src/main/index.ts | 17 +++++ src/main/sys/autoRun.ts | 62 +----------------- src/main/sys/misc.ts | 50 ++++++++++++++- src/main/utils/ipc.ts | 3 +- .../components/settings/general-config.tsx | 63 ++++++------------- src/renderer/src/utils/ipc.ts | 4 -- 8 files changed, 89 insertions(+), 112 deletions(-) diff --git a/changelog.md b/changelog.md index 1b15d08..d848222 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,7 @@ ### New Features - 支持删除 Webdav 备份文件 +- Windows 绕过UAC弹窗 - Esc关闭窗口 ### Bug Fixes diff --git a/electron-builder.yml b/electron-builder.yml index c558f6f..17e96bf 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -30,7 +30,6 @@ win: - nsis - 7z artifactName: ${name}-windows-${version}-${arch}-portable.${ext} - requestedExecutionLevel: highestAvailable executableName: mihomo-party nsis: artifactName: ${name}-windows-${version}-${arch}-setup.${ext} diff --git a/src/main/index.ts b/src/main/index.ts index a99c677..31044b8 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -11,14 +11,31 @@ import { createTray } from './resolve/tray' import { init } from './utils/init' import { join } from 'path' import { initShortcut } from './resolve/shortcut' +import { execSync } from 'child_process' +import { createElevateTask } from './sys/misc' export let mainWindow: BrowserWindow | null = null +if (process.platform === 'win32') { + try { + createElevateTask() + } catch (e) { + try { + execSync('schtasks /run /tn mihomo-party-run') + } catch (e) { + dialog.showErrorBox('首次启动请以管理员权限运行', '首次启动请以管理员权限运行') + } finally { + app.exit() + } + } +} + const gotTheLock = app.requestSingleInstanceLock() if (!gotTheLock) { app.quit() } + const initPromise = init() app.on('second-instance', async (_event, commandline) => { diff --git a/src/main/sys/autoRun.ts b/src/main/sys/autoRun.ts index 487683c..a50842b 100644 --- a/src/main/sys/autoRun.ts +++ b/src/main/sys/autoRun.ts @@ -1,6 +1,6 @@ -import { exec } from 'child_process' import { dataDir, exePath, homeDir } from '../utils/dirs' import { mkdir, readFile, rm, writeFile } from 'fs/promises' +import { exec } from 'child_process' import { existsSync } from 'fs' import { app } from 'electron' import { promisify } from 'util' @@ -126,63 +126,3 @@ export async function disableAutoRun(): Promise { await rm(desktopFilePath) } } - -const shortcutTaskXml = ` - - - ${new Date().toISOString()} - ${process.env.USERNAME} - - - - - InteractiveToken - HighestAvailable - - - - Parallel - false - false - false - false - false - - false - false - - true - true - false - false - false - PT72H - 7 - - - - ${exePath()} - - - - ` - -export async function createShortcut(): Promise { - if (process.platform === 'win32') { - const execPromise = promisify(exec) - const taskFilePath = path.join(dataDir(), `${appName}-run.xml`) - await writeFile(taskFilePath, Buffer.from(`\ufeff${shortcutTaskXml}`, 'utf-16le')) - await execPromise(`schtasks /create /tn "${appName}-run" /xml "${taskFilePath}" /f`) - const createShortcutCommand = ` -$shortcutPath = [System.IO.Path]::Combine([System.Environment]::GetFolderPath("Desktop"), "Mihomo Party.lnk") -$wshell = New-Object -ComObject WScript.Shell -$shortcut = $wshell.CreateShortcut($shortcutPath) -$shortcut.TargetPath = "C:\\Windows\\System32\\schtasks.exe" -$shortcut.Arguments = "/run /tn ${appName}-run" -$shortcut.Description = "Start Mihomo Party without UAC Prompt" -$shortcut.IconLocation = "${exePath()}" -$shortcut.WindowStyle = 7 -$shortcut.Save()` - await execPromise(createShortcutCommand, { shell: 'powershell' }) - } -} diff --git a/src/main/sys/misc.ts b/src/main/sys/misc.ts index af4a6c2..b511f40 100644 --- a/src/main/sys/misc.ts +++ b/src/main/sys/misc.ts @@ -1,9 +1,11 @@ -import { exec, execFile } from 'child_process' +import { exec, execFile, execSync } from 'child_process' import { dialog, nativeTheme } from 'electron' import { readFile } from 'fs/promises' import path from 'path' +import os from 'os' import { promisify } from 'util' import { exePath, mihomoCorePath, resourcesDir } from '../utils/dirs' +import { writeFileSync } from 'fs' export function getFilePath(ext: string[]): string[] | undefined { return dialog.showOpenDialogSync({ @@ -45,3 +47,49 @@ export async function setupFirewall(): Promise { export function setNativeTheme(theme: 'system' | 'light' | 'dark'): void { nativeTheme.themeSource = theme } + +const elevateTaskXml = ` + + + ${new Date().toISOString()} + ${process.env.USERNAME} + + + + + InteractiveToken + HighestAvailable + + + + Parallel + false + false + false + false + false + + false + false + + true + true + false + false + false + PT72H + 7 + + + + ${exePath()} + + + +` + +export function createElevateTask(): void { + const taskFilePath = path.join(os.tmpdir(), `mihomo-party-run.xml`) + writeFileSync(taskFilePath, Buffer.from(`\ufeff${elevateTaskXml}`, 'utf-16le')) + execSync(`schtasks /create /tn "mihomo-party-run" /xml "${taskFilePath}" /f`) +} diff --git a/src/main/utils/ipc.ts b/src/main/utils/ipc.ts index 753321d..bd6f460 100644 --- a/src/main/utils/ipc.ts +++ b/src/main/utils/ipc.ts @@ -21,7 +21,7 @@ import { stopMihomoConnections, stopMihomoLogs } from '../core/mihomoApi' -import { checkAutoRun, createShortcut, disableAutoRun, enableAutoRun } from '../sys/autoRun' +import { checkAutoRun, disableAutoRun, enableAutoRun } from '../sys/autoRun' import { getAppConfig, patchAppConfig, @@ -166,7 +166,6 @@ export function registerIpcMainHandlers(): void { ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) => ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action) ) - ipcMain.handle('createShortcut', ipcErrorWrapper(createShortcut)) ipcMain.handle('setNativeTheme', (_e, theme) => { setNativeTheme(theme) }) diff --git a/src/renderer/src/components/settings/general-config.tsx b/src/renderer/src/components/settings/general-config.tsx index 6d93ffb..10a98db 100644 --- a/src/renderer/src/components/settings/general-config.tsx +++ b/src/renderer/src/components/settings/general-config.tsx @@ -1,4 +1,4 @@ -import React, { Key, useState } from 'react' +import React, { Key } from 'react' import SettingCard from '../base/base-setting-card' import SettingItem from '../base/base-setting-item' import { Button, Select, SelectItem, Switch, Tab, Tabs } from '@nextui-org/react' @@ -7,7 +7,6 @@ import useSWR from 'swr' import { checkAutoRun, copyEnv, - createShortcut, disableAutoRun, enableAutoRun, isPortable, @@ -23,7 +22,6 @@ const GeneralConfig: React.FC = () => { const { data: enable, mutate: mutateEnable } = useSWR('checkAutoRun', checkAutoRun) const { data: portable, mutate: mutatePortable } = useSWR('isPortable', isPortable) const { appConfig, patchAppConfig } = useAppConfig() - const [creating, setCreating] = useState(false) const { setTheme } = useTheme() const { silentStart = false, @@ -166,46 +164,25 @@ const GeneralConfig: React.FC = () => { )} {platform === 'win32' && ( - <> - - - - - - - + + + )} { return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('quitApp')) } -export async function createShortcut(): Promise { - return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('createShortcut')) -} - export async function setNativeTheme(theme: 'system' | 'light' | 'dark'): Promise { return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setNativeTheme', theme)) }