4.3 Windows应用升级原理
确认下载的文件正确无误后,electron-updater将会触发update-downloaded事件,此时用户代码会请求用户确认升级,用户确认后将会执行electron-updater的quitAndInstall方法,此方法会退出当前应用,安装新下载的安装文件。
electron-updater除了在准备好升级安装包文件后触发update-downloaded事件外,在下载和检验过程中也会触发download-progress和checking-for-update事件,以便用户显示过程信息。如果下载的文件验证无效,electron-updater也会触发update-not-available事件。
退出当前应用并不难,electron本身就提供了API,代码如下所示:
require("electron").app.quit()
此方法执行后,一般情况下应用的大部分在途逻辑当即停止执行并释放资源,接着触发electron的quit事件,代码如下:
require("electron").app.once("quit", (_: Event, exitCode: number) => handler (exitCode))
启动新版本的安装文件的逻辑即在上述handler方法内执行,代码逻辑如下:
doInstall(options: InstallOptions): boolean { const args = ["--updated"] if (options.isSilent) { args.push("/S") } if (options.isForceRunAfter) { args.push("--force-run") } const packagePath = this.downloadedUpdateHelper == null ? null : this.down loadedUpdateHelper.packageFile if (packagePath != null) { args.push('--package-file=${packagePath}') } const callUsingElevation = (): void => { _spawn(path.join(process.resourcesPath!!, "elevate.exe"), [options.installer Path].concat(args)) .catch(e => this.dispatchError(e)) } if (options.isAdminRightsRequired) { this._logger.info("isAdminRightsRequired is set to true, run installer using elevate.exe") callUsingElevation() return true } _spawn(options.installerPath, args) .catch((e: Error) => { const errorCode = (e as NodeJS.ErrnoException).code this._logger.info('Cannot run installer: error code: ${errorCode}, error message: "${e.message}", will be executed again using elevate if EACCES"') if (errorCode === "UNKNOWN" || errorCode === "EACCES") { callUsingElevation() } else { this.dispatchError(e) } }) return true }
electron-updater使用了Node.js内置的child_process库启动安装文件,因为安装文件是通过NSIS打包工具打包而成,所以可以接纳一系列的命令行参数:
- --updated:以升级模式启动安装包,如果当前应用正在执行,则提示用户退出当前应用再安装升级包。
- /S:以静默安装方式启动安装包,静默安装方式不会显示任何界面,即使当前应用正在运行也不会提示用户退出程序。
如果打包应用时为electron-builder提供了如下配置,则应用安装新版本安装包时,会以管理员的身份启动新版本安装包。
electronBuilder.build({ config: { win:{ requestedExecutionLevel: "requireAdministrator", // 或highestAvailable ... }, ... }, ... })
如果启动应用失败,得到了EACCES或UNKNOWN的错误码,也会尝试以管理员的身份启动安装包。
这个操作是通过elevate.exe完成的,这个可执行程序是electron-builder通过NSIS内置到应用程序内的,文件存放路径如下:
C:\Program Files (x86)\yourProductName\resources\elevate.exe
在命令行下执行此程序,并把目标程序路径当做参数传入命令行,目标程序则以管理员身份启动运行。它还支持很多其他的参数,比如等待目标程序退出、为目标程序传参等。你可以通过如下命令行指令查看其支持的参数:
> cd C:\Program Files (x86)\yourProductName\resources\ > elevate -?
这是一个非常有用的工具,虽然electron-builder携带它是为了给自己服务的,但我们也可以正常使用它,假设你的产品需要以管理员的身份启动一个第三方应用程序,就可以通过Node.js的内置模块child_process来使用elevate.exe启动你的目标程序。