From dd27ec27f262600fff44c0d79518158ed55894e9 Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Tue, 27 Oct 2026 16:53:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8IExpress=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=8F=AF=E5=AE=89=E8=A3=85=E5=88=86=E5=8F=91=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/package.mjs | 47 +++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/scripts/package.mjs b/scripts/package.mjs index 092e1d7..0c9305f 100644 --- a/scripts/package.mjs +++ b/scripts/package.mjs @@ -14,7 +14,8 @@ const productFolderName = `RPA-Studio-${version}-win-x64`; const productFolder = path.join(releaseRoot, productFolderName); const zipPath = path.join(releaseRoot, `${productFolderName}.zip`); const setupPath = path.join(releaseRoot, `RPA-Studio-Setup-${version}-win-x64.exe`); -const setupArchive = path.join(releaseRoot, `${productFolderName}.7z`); +const installerPayload = path.join(releaseRoot, ".installer-payload"); +const installerSed = path.join(releaseRoot, ".installer.sed"); function assertInsideRelease(target) { const relative = path.relative(releaseRoot, path.resolve(target)); @@ -29,7 +30,7 @@ function run(command, args) { } fs.mkdirSync(releaseRoot, { recursive: true }); -for (const target of [productFolder, zipPath, setupPath, setupArchive]) { +for (const target of [productFolder, zipPath, setupPath, installerPayload, installerSed]) { assertInsideRelease(target); fs.rmSync(target, { recursive: true, force: true }); } @@ -144,16 +145,38 @@ zip.writeZip(zipPath); const zipSha256 = createHash("sha256").update(fs.readFileSync(zipPath)).digest("hex"); let setupSha256 = ""; -const sevenZip = "C:/Program Files/7-Zip/7z.exe"; -const sfxModule = "C:/Program Files/7-Zip/7z.sfx"; -if (fs.existsSync(sevenZip) && fs.existsSync(sfxModule)) { - console.log("[package] setup sfx"); - const archived = spawnSync(sevenZip, ["a", "-t7z", setupArchive, ".", "-mx=9"], { cwd: productFolder, stdio: "inherit" }); - if (archived.status !== 0) throw new Error(`7-Zip 打包失败,退出码 ${archived.status}`); - const config = Buffer.from(`;!@Install@!UTF-8!\nTitle=\"RPA Studio ${version}\"\nBeginPrompt=\"将 RPA Studio 安装到当前用户并创建桌面快捷方式?\"\nRunProgram=\"安装到本机.cmd\"\nGUIMode=\"1\"\n;!@InstallEnd@!\n`, "utf8"); - fs.writeFileSync(setupPath, Buffer.concat([fs.readFileSync(sfxModule), config, fs.readFileSync(setupArchive)])); - setupSha256 = createHash("sha256").update(fs.readFileSync(setupPath)).digest("hex"); -} +const iexpress = path.join(process.env.SystemRoot || "C:/Windows", "System32", "iexpress.exe"); +if (!fs.existsSync(iexpress)) throw new Error(`找不到 Windows IExpress:${iexpress}`); +console.log("[package] setup iexpress"); +fs.mkdirSync(installerPayload, { recursive: true }); +fs.copyFileSync(zipPath, path.join(installerPayload, "payload.zip")); +fs.writeFileSync(path.join(installerPayload, "install.cmd"), [ + "@echo off", + "chcp 65001 >nul", + "set \"TARGET=%LOCALAPPDATA%\\Programs\\RPA Studio\"", + "set \"STAGE=%TEMP%\\RPA-Studio-Install-%RANDOM%\"", + "powershell -NoProfile -ExecutionPolicy Bypass -Command \"Expand-Archive -LiteralPath '%~dp0payload.zip' -DestinationPath '%STAGE%' -Force\"", + `robocopy "%STAGE%\\${productFolderName}" "%TARGET%" /E /R:2 /W:1 /NFL /NDL /NJH /NJS /NP >nul`, + "powershell -NoProfile -ExecutionPolicy Bypass -Command \"$w=New-Object -ComObject WScript.Shell;$s=$w.CreateShortcut([IO.Path]::Combine([Environment]::GetFolderPath('Desktop'),'RPA Studio.lnk'));$s.TargetPath=[IO.Path]::Combine($env:LOCALAPPDATA,'Programs','RPA Studio','RPA Studio.exe');$s.WorkingDirectory=[IO.Path]::Combine($env:LOCALAPPDATA,'Programs','RPA Studio');$s.Save()\"", + "start \"RPA Studio\" \"%TARGET%\\RPA Studio.exe\"", + "rmdir /s /q \"%STAGE%\"", + "exit /b 0" +].join("\r\n"), "utf8"); +const sourceDir = `${installerPayload.replace(/\//g, "\\")}\\`; +fs.writeFileSync(installerSed, [ + "[Version]", "Class=IEXPRESS", "SEDVersion=3", "[Options]", "PackagePurpose=InstallApp", "ShowInstallProgramWindow=1", + "HideExtractAnimation=0", "UseLongFileName=1", "InsideCompressed=0", "CAB_FixedSize=0", "CAB_ResvCodeSigning=0", + "RebootMode=N", "InstallPrompt=%InstallPrompt%", "DisplayLicense=", "FinishMessage=%FinishMessage%", + `TargetName=${setupPath}`, `FriendlyName=RPA Studio ${version}`, "AppLaunched=install.cmd", "PostInstallCmd=", + "AdminQuietInstCmd=install.cmd", "UserQuietInstCmd=install.cmd", "SourceFiles=SourceFiles", "[Strings]", + `InstallPrompt=Install RPA Studio ${version} for the current Windows user?`, "FinishMessage=RPA Studio installation completed.", + "FILE0=payload.zip", "FILE1=install.cmd", "[SourceFiles]", `SourceFiles0=${sourceDir}`, "[SourceFiles0]", "%FILE0%=", "%FILE1%=", "" +].join("\r\n"), "utf8"); +const builtSetup = spawnSync(iexpress, ["/N", installerSed], { cwd: releaseRoot, stdio: "inherit", windowsHide: true }); +if (builtSetup.status !== 0 || !fs.existsSync(setupPath)) throw new Error(`IExpress 安装包生成失败,退出码 ${builtSetup.status}`); +setupSha256 = createHash("sha256").update(fs.readFileSync(setupPath)).digest("hex"); +fs.rmSync(installerPayload, { recursive: true, force: true }); +fs.rmSync(installerSed, { force: true }); const sums = [`${zipSha256} ${path.basename(zipPath)}`]; if (setupSha256) sums.push(`${setupSha256} ${path.basename(setupPath)}`); fs.writeFileSync(path.join(releaseRoot, "SHA256SUMS.txt"), `${sums.join("\r\n")}\r\n`, "utf8");