14

NSIS 打包 Electron 项目的注意事项(拖拽、权限、兼容性等)

 2 years ago
source link: https://www.mycode.net.cn/platform/2838.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

我自己本人不做 Electron 的开发,但有一位合作伙伴在使用 NSIS 打包 Electron 应用的时候遇到了一些问题,主要问题有以下几个,先记录下来,然后追个击破。

  • 打包后应用在 Windows 7 无法直接运行,需要修改兼容性为 Windows 7 才可以使用
  • 打包后安装或者卸载时应用在运行会安装或者卸载失败,无法替换或删除应用(这个与 Electron 无关但也介绍一下)
  • 打包后应用第一次启动无法使用拖拽功能

脚本设置启动程序兼容性

设置程序兼容性有两种方式,一种是手动右键修改,但这种方式明显不可能让用户自己去操作,所以我们需要另外一种方式就是在安装程序后自动写入一个注册表,告诉系统我们启动自己的应用时使用 Windows 7 兼容模式运行,示例注册表如下:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Program Files (x86)\\MyOffice\\avic.exe"="WIN7RTM"

要在 NSIS 的脚本中写入这个注册表,可以像下面这样操作:

Section -Post
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr HKCU "Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" "$INSTDIR\avic.exe" "WIN7RTM"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\avic.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\avic.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 官网下载。以下是示例脚本:

Function .onInit
  FindProcDLL::FindProc "avic.exe"
  Pop $R0
  IntCmp $R0 1 0 no_run
  MessageBox MB_OKCANCEL|MB_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_ICONQUESTION|MB_YESNO|MB_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 打包后安装包程序默认是以管理员身份启动的,第一次安装完成后自动启动应用时会继承安装包的权限(管理员)导致拖拽功能无法使用了,而直接从桌面运行快捷方式是没问题的。解决这个问题的办法就是让安装包不以管理员方式运行就可以了。在初始化代码中加如下代码,让安装包使用普通用户权限:

RequestExecutionLevel user

当安装包没有管理员权限后,你安装到 C:\Program Files 目录就会被拒绝,这时你可以参考想 VSCode 一样,将应用安装到 C:\Users\Administrator\AppData\Local\Programs 目录下,来避免权限问题。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK