我自己本人不做 Electron 的开发,但有一位合作伙伴在使用 NSIS 打包 Electron 应用的时候遇到了一些问题,主要问题有以下几个,先记录下来,然后追个击破。
- 打包后应用在 Windows 7 无法直接运行,需要修改兼容性为 Windows 7 才可以使用
- 打包后安装或者卸载时应用在运行会安装或者卸载失败,无法替换或删除应用(这个与 Electron 无关但也介绍一下)
- 打包后应用第一次启动无法使用拖拽功能
脚本设置启动程序兼容性
设置程序兼容性有两种方式,一种是手动右键修改,但这种方式明显不可能让用户自己去操作,所以我们需要另外一种方式就是在安装程序后自动写入一个注册表,告诉系统我们启动自己的应用时使用 Windows 7 兼容模式运行,示例注册表如下:
代码语言:javascript复制Windows Registry Editor Version 5.00
[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionAppCompatFlagsLayers]
"C:\Program Files (x86)\MyOffice\avic.exe"="WIN7RTM"
要在 NSIS 的脚本中写入这个注册表,可以像下面这样操作:
代码语言:javascript复制Section -Post
WriteUninstaller "$INSTDIRuninst.exe"
WriteRegStr HKCU "SoftwareMicrosoftWindows NTCurrentVersionAppCompatFlagsLayers" "$INSTDIRavic.exe" "WIN7RTM"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIRavic.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIRuninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIRavic.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
如代码第三行所示,我们将应用安装所在目录下的执行程序通过 WriteRegStr
方法写入到了注册表中,给它设置的值是 WIN7RTM
,这样应用在启动的时候,就会以 Windows 7 兼容性模式运行了。
安装或卸载前结束应用
需要两个插件,一个是 KillProcDLL.dll,另一个是 FindProcDLL.dll,这两个插件均可以从 NSIS 官网下载。以下是示例脚本:
代码语言:javascript复制Function .onInit
FindProcDLL::FindProc "avic.exe"
Pop $R0
IntCmp $R0 1 0 no_run
MessageBox MB_OKCANCELMB_ICONSTOP "安装程序检测到 ${PRODUCT_NAME} 正在运行。$r$n$r$n点击 “确定” 强制关闭${PRODUCT_NAME},继续安装。$r$n点击 “取消” 退出安装程序。" IDCANCEL Exit
KillProcDLL::KillProc "avic.exe"
Sleep 1000
FindProcDLL::FindProc "avic.exe"
Pop $R0
IntCmp $R0 1 0 no_run
Exit:
Quit
no_run:
FunctionEnd
Function un.onInit
MessageBox MB_ICONQUESTIONMB_YESNOMB_DEFBUTTON2 "您确定要卸载[MyOffice]?" IDYES 2
Abort
#检测程序是否运行
FindProcDLL::FindProc "avic.exe"
Pop $R0
IntCmp $R0 1 0 no_run
KillProcDLL::KillProc "avic.exe"
Sleep 1000
FindProcDLL::FindProc "avic.exe"
Pop $R0
IntCmp $R0 1 0 no_run
Quit
no_run:
FunctionEnd
打包后无法使用拖拽功能
经过排查发现,NSIS 打包后安装包程序默认是以管理员身份启动的,第一次安装完成后自动启动应用时会继承安装包的权限(管理员)导致拖拽功能无法使用了,而直接从桌面运行快捷方式是没问题的。解决这个问题的办法就是让安装包不以管理员方式运行就可以了。在初始化代码中加如下代码,让安装包使用普通用户权限:
代码语言:javascript复制RequestExecutionLevel user
当安装包没有管理员权限后,你安装到 C:Program Files 目录就会被拒绝,这时你可以参考想 VSCode 一样,将应用安装到 C:UsersAdministratorAppDataLocalPrograms
目录下,来避免权限问题。