diff --git a/misc/nsis/graphics/install.ico b/misc/nsis/graphics/install.ico new file mode 100755 index 000000000..8a30f612e Binary files /dev/null and b/misc/nsis/graphics/install.ico differ diff --git a/misc/nsis/graphics/readme.txt b/misc/nsis/graphics/readme.txt new file mode 100755 index 000000000..b99dee86c --- /dev/null +++ b/misc/nsis/graphics/readme.txt @@ -0,0 +1,2 @@ +These are modified versions of 'orange-install.ico', 'orange-uninstall.ico' +and 'orange.bmp' graphics of the NSIS distribution. \ No newline at end of file diff --git a/misc/nsis/graphics/uninstall.ico b/misc/nsis/graphics/uninstall.ico new file mode 100755 index 000000000..94ea5bce3 Binary files /dev/null and b/misc/nsis/graphics/uninstall.ico differ diff --git a/misc/nsis/graphics/wizard.bmp b/misc/nsis/graphics/wizard.bmp new file mode 100755 index 000000000..a48c8ee03 Binary files /dev/null and b/misc/nsis/graphics/wizard.bmp differ diff --git a/misc/nsis/install.nsh b/misc/nsis/install.nsh new file mode 100755 index 000000000..267fd0d90 --- /dev/null +++ b/misc/nsis/install.nsh @@ -0,0 +1,484 @@ +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +# NSIS installer header. Uses NsisMultiUser plugin and contains portions of +# its demo code, copyright 2017 Richard Drizin, Alex Mitev. + + +;Languages (first is default language) - must be inserted after all pages +!insertmacro MUI_LANGUAGE "English" +!insertmacro MULTIUSER_LANGUAGE_INIT + +; Reserve files +!insertmacro MUI_RESERVEFILE_LANGDLL + +!macro MSI32_STACK + Push "${MSI32_010}" + Push "${MSI32_011}" + Push "${MSI32_012}" + Push "${MSI32_013}" + Push "${MSI32_014}" + Push "${MSI32_020}" + Push "${MSI32_021}" + Push "${MSI32_030}" + Push "${MSI32_040}" + Push "${MSI32_041}" + Push "${MSI32_050}" + Push "${MSI32_051}" + Push "${MSI32_060}" + Push "${MSI32_061}" + Push "${MSI32_062}" + Push "${MSI32_070}" + Push "${MSI32_080}" + Push "${MSI32_081}" + Push "${MSI32_082}" + Push "${MSI32_084}" + Push "${MSI32_090}" + Push "${MSI32_091}" + Push "${MSI32_100}" + Push "${MSI32_101}" +!macroend + +!macro MSI64_STACK + Push "${MSI64_010}" + Push "${MSI64_011}" + Push "${MSI64_012}" + Push "${MSI64_013}" + Push "${MSI64_014}" + Push "${MSI64_020}" + Push "${MSI64_021}" + Push "${MSI64_030}" + Push "${MSI64_040}" + Push "${MSI64_041}" + Push "${MSI64_050}" + Push "${MSI64_051}" + Push "${MSI64_060}" + Push "${MSI64_061}" + Push "${MSI64_062}" + Push "${MSI64_070}" + Push "${MSI64_080}" + Push "${MSI64_081}" + Push "${MSI64_082}" + Push "${MSI64_084}" + Push "${MSI64_090}" + Push "${MSI64_091}" + Push "${MSI64_100}" + Push "${MSI64_101}" +!macroend + +!macro CheckMSI + ${foreach} $9 ${MSI_COUNT} 1 - 1 + Pop $R1 + ReadRegStr $0 HKLM "${REG_UN}\$R1" "DisplayName" + ${if} $0 == "${PRODUCT_NAME}" + ${exitfor} + ${else} + StrCpy $R1 "" + ${endif} + ${next} +!macroend + +!macro CheckOldNSIS + ReadRegStr $R0 HKLM "${REG_UN}\${PRODUCT_NAME}" "QuietUninstallString" + ${if} $R0 != "" + ReadRegStr $R0 HKLM "${REG_UN}\${PRODUCT_NAME}" "UninstallString" + ${if} $R0 != "" + System::Call 'Shlwapi::PathUnquoteSpaces(t r10r10)' + IfFileExists $R0 +2 0 + StrCpy $R0 "" + ${endif} + ${endif} +!macroend + +!macro RemoveOld UninstCmd + ClearErrors + ExecWait "${UninstCmd}" + ${if} ${errors} + MessageBox MB_ICONSTOP "The uninstaller has failed to complete.$\r$\nPlease restart Windows and try again." /SD IDOK + Abort + ${endif} +!macroend + +; Sections +InstType "Full" +InstType "Typical" +InstType "Minimal" + +Section "Core Files (required)" SectionCoreFiles + SectionIn 1 2 3 RO + + ; if there's an installed version, uninstall it first (I chose not to start the uninstaller silently, so that user sees what failed) + ; if both per-user and per-machine versions are installed, unistall the one that matches $MultiUser.InstallMode + StrCpy $0 "" + ${if} $HasCurrentModeInstallation = 1 + StrCpy $0 "$MultiUser.InstallMode" + ${else} + !if ${MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS} = 0 + ${if} $HasPerMachineInstallation = 1 + StrCpy $0 "AllUsers" ; if there's no per-user installation, but there's per-machine installation, uninstall it + ${elseif} $HasPerUserInstallation = 1 + StrCpy $0 "CurrentUser" ; if there's no per-machine installation, but there's per-user installation, uninstall it + ${endif} + !endif + ${endif} + + ${if} "$0" != "" + ${if} $0 == "AllUsers" + StrCpy $1 "$PerMachineUninstallString" + StrCpy $3 "$PerMachineInstallationFolder" + ${else} + StrCpy $1 "$PerUserUninstallString" + StrCpy $3 "$PerUserInstallationFolder" + ${endif} + ${if} ${silent} + StrCpy $2 "/S" + ${else} + StrCpy $2 "" + ${endif} + + HideWindow + ClearErrors + StrCpy $0 0 + ExecWait '$1 /SS $2 _?=$3' $0 ; $1 is quoted in registry; the _? param stops the uninstaller from copying itself to the temporary directory, which is the only way for ExecWait to work + + ${if} ${errors} ; stay in installer + SetErrorLevel 2 ; Installation aborted by script + BringToFront + Abort "Error executing uninstaller." + ${else} + ${Switch} $0 + ${Case} 0 ; uninstaller completed successfully - continue with installation + BringToFront + ${Break} + ${Case} 1 ; Installation aborted by user (cancel button) + ${Case} 2 ; Installation aborted by script + SetErrorLevel $0 + Quit ; uninstaller was started, but completed with errors - Quit installer + ${Default} ; all other error codes - uninstaller could not start, elevate, etc. - Abort installer + SetErrorLevel $0 + BringToFront + Abort "Error executing uninstaller." + ${EndSwitch} + ${endif} + + !insertmacro DeleteRetryAbort "$3\${UNINSTALL_FILENAME}" ; the uninstaller doesn't delete itself when not copied to the temp directory + RMDir "$3" + ${endif} + + ; Remove the old uninstaller if it's leftover + IfFileExists "$INSTDIR\uninst.exe" 0 +2 + Delete "$INSTDIR\uninst.exe" + + SetOutPath $INSTDIR + ; Write uninstaller and registry uninstall info as the first step, + ; so that the user has the option to run the uninstaller if something goes wrong + WriteUninstaller "${UNINSTALL_FILENAME}" + ; or this if you're using signing: + ; File "${UNINSTALL_FILENAME}" + !insertmacro MULTIUSER_RegistryAddInstallInfo ; add registry keys + ${if} ${silent} ; MUI doesn't write language in silent mode + WriteRegStr "${MUI_LANGDLL_REGISTRY_ROOT}" "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}" $LANGUAGE + ${endif} + + File /r "${DIST_DIR}\*.*" +SectionEnd + +SectionGroup /e "System Integration" SectionGroupIntegration + +Section "Register with Windows" SectionWindowsRegister + SectionIn 1 2 + + ; No HKCU support for Windows versions earlier than Win8 + ${if} $MultiUser.InstallMode == "AllUsers" + ${orif} ${AtLeastWin8} + ;StartMenuInternet + StrCpy $0 "$INSTDIR\${PROGEXE}" + System::Call 'kernel32::GetLongPathNameW(t r0, t .r1, i ${NSIS_MAX_STRLEN}) i .r2' + + StrCpy $0 "SOFTWARE\Clients\StartMenuInternet\${PRODUCT_NAME}" + + WriteRegStr SHCTX "$0" "" "${PRODUCT_NAME}" + + WriteRegStr SHCTX "$0\DefaultIcon" "" "$1,0" + + WriteRegDWORD SHCTX "$0\InstallInfo" "IconsVisible" 1 + + WriteRegStr SHCTX "$0\shell\open\command" "" "$\"$1$\"" + + WriteRegStr SHCTX "$0\shell\properties" "" "${PRODUCT_NAME} settings" + WriteRegStr SHCTX "$0\shell\properties\command" "" "$\"$1$\" ${SHELL_PROPERTIES}" + + WriteRegStr SHCTX "$0\shell\safemode" "" "${PRODUCT_NAME} safe mode" + WriteRegStr SHCTX "$0\shell\safemode\command" "" "$\"$1$\" ${SHELL_SAFEMODE}" + + WriteRegStr SHCTX "$0\Capabilities" "ApplicationDescription" "${COMMENTS}" + WriteRegStr SHCTX "$0\Capabilities" "ApplicationIcon" "$1,0" + WriteRegStr SHCTX "$0\Capabilities" "ApplicationName" "${PRODUCT_NAME}" + + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".htm" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".html" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".shtml" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".svg" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".xht" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".xhtml" "${PRODUCT_NAME}HTML" + WriteRegStr SHCTX "$0\Capabilities\FileAssociations" ".webp" "${PRODUCT_NAME}HTML" + + WriteRegStr SHCTX "$0\Capabilities\StartMenu" "StartMenuInternet" "${PRODUCT_NAME}" + + WriteRegStr SHCTX "$0\Capabilities\URLAssociations" "ftp" "${PRODUCT_NAME}URL" + WriteRegStr SHCTX "$0\Capabilities\URLAssociations" "http" "${PRODUCT_NAME}URL" + WriteRegStr SHCTX "$0\Capabilities\URLAssociations" "https" "${PRODUCT_NAME}URL" + + ; Register Application + WriteRegStr SHCTX "SOFTWARE\RegisteredApplications" "${PRODUCT_NAME}" "$0\Capabilities" + + ; Associate file types + WriteRegStr SHCTX "SOFTWARE\Classes\.htm\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.html\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.shtml\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.svg\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.xht\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.xhtml\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\.webp\OpenWithProgids" "${PRODUCT_NAME}HTML" "" + + ; HTML and URL handlers + StrCpy $2 "${PRODUCT_NAME}HTML" + StrCPY $3 "${PRODUCT_NAME} HTML Document" + WriteRegHandler: + WriteRegStr SHCTX "SOFTWARE\Classes\$2" "" "$3" + WriteRegStr SHCTX "SOFTWARE\Classes\$2" "FriendlyTypeName" "$3" + WriteRegDWord SHCTX "SOFTWARE\Classes\$2" "EditFlags" 0x00000002 + WriteRegStr SHCTX "SOFTWARE\Classes\$2\DefaultIcon" "" "$1,0" + WriteRegStr SHCTX "SOFTWARE\Classes\$2\shell" "" "open" + WriteRegStr SHCTX "SOFTWARE\Classes\$2\shell\open\command" "" "$\"$1$\" $\"%1$\"" + WriteRegStr SHCTX "SOFTWARE\Classes\$2\shell\open\ddeexec" "" "" + StrCmp "$2" "${PRODUCT_NAME}HTML" 0 +4 + StrCpy $2 "${PRODUCT_NAME}URL" + StrCpy $3 "${PRODUCT_NAME} URL" + Goto WriteRegHandler + WriteRegStr SHCTX "SOFTWARE\Classes\$2" "URL Protocol" "" + ${endif} +SectionEnd + +Section /o "Set as default browser" SectionDefaultBrowser + SectionIn 1 + + ReadRegStr $0 HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId" + ReadRegStr $1 HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" "ProgId" + ReadRegStr $2 HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.htm\UserChoice" "ProgId" + ReadRegStr $3 HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "ProgId" + ${ifnot} $0 == "${PRODUCT_NAME}URL" + ${orifnot} $1 == "${PRODUCT_NAME}URL" + ${orifnot} $2 == "${PRODUCT_NAME}HTML" + ${orifnot} $3 == "${PRODUCT_NAME}HTML" + ${if} ${AtLeastWin10} + ExecShell "open" "ms-settings:defaultapps" + ${elseif} ${AtLeastWin8} + ExecShell "open" "control.exe" "/name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=${PRODUCT_NAME}" + ${else} + StrCmp $0 "${PRODUCT_NAME}URL" +2 0 + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId" "${PRODUCT_NAME}URL" + StrCmp $1 "${PRODUCT_NAME}URL" +2 0 + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" "ProgId" "${PRODUCT_NAME}URL" + StrCmp $2 "${PRODUCT_NAME}HTML" +3 0 + DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.htm\UserChoice" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.htm\UserChoice" "ProgId" "${PRODUCT_NAME}HTML" + StrCmp $3 "${PRODUCT_NAME}HTML" +3 0 + DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "ProgId" "${PRODUCT_NAME}HTML" + ${endif} + ${endif} +SectionEnd + +SectionGroupEnd + +SectionGroup "Shortcuts" SectionGroupShortcuts + +Section "Dektop Icon" SectionDesktopIcon + SectionIn 1 2 + + !insertmacro MULTIUSER_GetCurrentUserString $0 + CreateShortCut "$DESKTOP\${PRODUCT_NAME}$0.lnk" "$INSTDIR\${PROGEXE}" +SectionEnd + +Section "Start Menu Icon" SectionStartMenuIcon + SectionIn 1 2 + + !insertmacro MULTIUSER_GetCurrentUserString $0 + CreateShortCut "$STARTMENU\${PRODUCT_NAME}$0.lnk" "$INSTDIR\${PROGEXE}" +SectionEnd + +SectionGroupEnd + +Section "-Write Install Info" ; hidden section, write install info as the final step + !insertmacro MULTIUSER_RegistryAddInstallSizeInfo + !insertmacro MULTIUSER_GetCurrentUserString $0 + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "HelpLink" "${HELP_LINK}" + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "URLInfoAbout" "${URL_ABOUT}" + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "URLUpdateInfo" "${URL_UPDATE}" + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "Comments" "${COMMENTS}" + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "Contact" "${CONTACT}" + + ; Add InstallDate String + System::Call /NOUNLOAD '*(&i2,&i2,&i2,&i2,&i2,&i2,&i2,&i2) i .r9' + System::Call /NOUNLOAD 'kernel32::GetLocalTime(i)i(r9)' + System::Call /NOUNLOAD '*$9(&i2,&i2,&i2,&i2,&i2,&i2,&i2,&i2)i(.r1,.r2,.r3,.r4,.r5,.r6,.r7,)' + System::Free $9 + IntCmp $2 9 0 0 +2 + StrCpy $2 '0$2' + IntCmp $4 9 0 0 +2 + StrCpy $4 '0$4' + WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_UNINSTALL_REGISTRY_KEY_PATH}$0" "InstallDate" "$1$2$4" + + ; Refresh Shell Icons + System::Call "shell32::SHChangeNotify(i 0x08000000, i 0, i 0, i 0)" +SectionEnd + +; Modern install component descriptions +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SectionCoreFiles} "Core files required to run ${PRODUCT_NAME}." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionGroupIntegration} "Integrate ${PRODUCT_NAME} with the Operating System." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionWindowsRegister} "Register protocols and file extensions with ${PRODUCT_NAME}." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionDefaultBrowser} "Set ${PRODUCT_NAME} as the default Web browser." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionGroupShortcuts} "Create shortcut icons to run ${PRODUCT_NAME}." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionDesktopIcon} "Create ${PRODUCT_NAME} icon on the Desktop." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionStartMenuIcon} "Create ${PRODUCT_NAME} icon in the Start Menu." +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +; Callbacks +Function .onInit + !insertmacro CheckPlatform ${PLATFORM} + !insertmacro CheckMinWinVer ${MIN_WIN_VER} + ${ifnot} ${UAC_IsInnerInstance} + !insertmacro CheckSingleInstance "Setup" "Global" "${SETUP_MUTEX}" + !insertmacro CheckSingleInstance "Application" "Local" "${APP_MUTEX}" + ${endif} + + ; Detect existing setup from previous installers + !insertmacro CheckOldNSIS + !insertmacro MSI32_STACK + !insertmacro CheckMSI + ${if} $R1 == "" + ${andif} ${RunningX64} + SetRegView 64 ; Will be set again by MULTIUSER_INIT + !insertmacro MSI64_STACK + !insertmacro CheckMSI + ${endif} + ${if} $R0 != "" + ${orif} $R1 != "" + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "An older version of ${PRODUCT_NAME} is already installed.$\n\ + $\nClick `OK` to remove the previous version and continue,$\n\ + or `Cancel` to cancel this upgrade." \ + IDOK +2 + Abort + ${if} $R0 != "" + ${GetParent} $R0 $0 + ${GetFileName} $R0 $1 + ; Using cmd.exe for elevation to work + !insertmacro RemoveOld "cmd.exe /c start /wait /d $\"$0$\" $1 /S _?=$0" + ${endif} + ${if} $R1 != "" + !insertmacro RemoveOld "msiexec.exe /X$R1 /passive /promptrestart" + ${endif} + ${endif} + + !insertmacro MULTIUSER_INIT + + ${if} $IsInnerInstance = 0 + !insertmacro MUI_LANGDLL_DISPLAY + ${endif} +FunctionEnd + +Function .onSelChange + ${if} ${SectionIsSelected} ${SectionDefaultBrowser} + !insertmacro SetSectionFlag ${SectionWindowsRegister} ${SF_RO} + !insertmacro SelectSection ${SectionWindowsRegister} + ${else} + !insertmacro ClearSectionFlag ${SectionWindowsRegister} ${SF_RO} + ${endif} +FunctionEnd + +Function PageWelcomeLicensePre + ${if} $InstallShowPagesBeforeComponents = 0 + Abort ; don't display the Welcome and License pages for the inner instance + ${endif} +FunctionEnd + +Function PageInstallModeChangeMode + ; Disable integration for single user install on Win7 and older, as it's not supported + ${if} $MultiUser.InstallMode == "CurrentUser" + ${andif} ${AtMostWin7} + SectionSetText ${SectionGroupIntegration} "System Integration (not supported)" + IntOP $0 ${SF_RO} & ${SECTION_OFF} + SectionSetFlags ${SectionWindowsRegister} $0 + SectionSetFlags ${SectionDefaultBrowser} $0 + !insertmacro SetSectionFlag ${SectionGroupIntegration} ${SF_RO} + !insertmacro ClearSectionFlag ${SectionGroupIntegration} ${SF_EXPAND} + ${else} + ; This is necessary because if the installer started under Win7/Vista as Administrator with UAC disabled, + ; going back to All users after first selecting Single user, the integration component would still be disabled + SectionSetText ${SectionGroupIntegration} "System Integration" + !insertmacro ClearSectionFlag ${SectionWindowsRegister} ${SF_RO} + !insertmacro ClearSectionFlag ${SectionDefaultBrowser} ${SF_RO} + !insertmacro ClearSectionFlag ${SectionGroupIntegration} ${SF_RO} + !insertmacro SetSectionFlag ${SectionGroupIntegration} ${SF_EXPAND} + !insertmacro SelectSection ${SectionWindowsRegister} + + ; Select 'Default browser' if already set in registry + ReadRegStr $0 HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId" + ${if} $0 == "${PRODUCT_NAME}URL" + !insertmacro SetSectionFlag ${SectionWindowsRegister} ${SF_RO} + !insertmacro SelectSection ${SectionDefaultBrowser} + ${else} + !insertmacro UnselectSection ${SectionDefaultBrowser} + ${endif} + ${endif} +FunctionEnd + +Function PageDirectoryPre + GetDlgItem $0 $HWNDPARENT 1 + SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^InstallBtn)" ; this is the last page before installing +FunctionEnd + +Function PageDirectoryShow + ${if} $CmdLineDir != "" + FindWindow $R1 "#32770" "" $HWNDPARENT + + GetDlgItem $0 $R1 1019 ; Directory edit + SendMessage $0 ${EM_SETREADONLY} 1 0 ; read-only is better than disabled, as user can copy contents + + GetDlgItem $0 $R1 1001 ; Browse button + EnableWindow $0 0 + ${endif} +FunctionEnd + +Function PageFinishRun + ; the installer might exit too soon before the application starts and it loses the right to be the foreground window and starts in the background + ; however, if there's no active window when the application starts, it will become the active window, so we hide the installer + HideWindow + ; the installer will show itself again quickly before closing (w/o Taskbar button), we move it offscreen + !define SWP_NOSIZE 0x0001 + !define SWP_NOZORDER 0x0004 + System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($HWNDPARENT, 0, -1000, -1000, 0, 0, ${SWP_NOZORDER}|${SWP_NOSIZE})" + + !insertmacro UAC_AsUser_ExecShell "open" "$INSTDIR\${PROGEXE}" "" "$INSTDIR" "" +FunctionEnd + +Function .onInstFailed + MessageBox MB_ICONSTOP "${PRODUCT_NAME} ${VERSION} could not be fully installed.$\r$\nPlease, restart Windows and run the setup program again." /SD IDOK +FunctionEnd diff --git a/misc/nsis/install_pages.nsh b/misc/nsis/install_pages.nsh new file mode 100755 index 000000000..92328c66b --- /dev/null +++ b/misc/nsis/install_pages.nsh @@ -0,0 +1,62 @@ +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +# NSIS pages header. Uses NsisMultiUser plugin and contains portions of +# its demo code, copyright 2017 Richard Drizin, Alex Mitev. + + +; NsisMultiUser optional defines +!define MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS 0 +!define MULTIUSER_INSTALLMODE_ALLOW_ELEVATION 1 +!define MULTIUSER_INSTALLMODE_ALLOW_ELEVATION_IF_SILENT 0 +!define MULTIUSER_INSTALLMODE_DEFAULT_ALLUSERS 1 +!if ${PLATFORM} == "win64" + !define MULTIUSER_INSTALLMODE_64_BIT 1 +!endif +!define MULTIUSER_INSTALLMODE_DISPLAYNAME "${PRODUCT_NAME} ${VERSION} (${ARCH})" + +; Interface Settings +!define MUI_ABORTWARNING ; Show a confirmation when cancelling the installation +!define MUI_LANGDLL_ALLLANGUAGES ; Show all languages, despite user's codepage + +; Remember the installer language +!define MUI_LANGDLL_REGISTRY_ROOT "SHCTX" +!define MUI_LANGDLL_REGISTRY_KEY "${SETTINGS_REG_KEY}" +!define MUI_LANGDLL_REGISTRY_VALUENAME "Language" + +; Pages +!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomeLicensePre +!insertmacro MUI_PAGE_WELCOME + +!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomeLicensePre +!insertmacro MUI_PAGE_LICENSE "${LICENSE_FILE}" + +!define MULTIUSER_INSTALLMODE_CHANGE_MODE_FUNCTION PageInstallModeChangeMode +!insertmacro MULTIUSER_PAGE_INSTALLMODE + +!define MUI_COMPONENTSPAGE_SMALLDESC +!insertmacro MUI_PAGE_COMPONENTS + +!define MUI_PAGE_CUSTOMFUNCTION_PRE PageDirectoryPre +!define MUI_PAGE_CUSTOMFUNCTION_SHOW PageDirectoryShow +!insertmacro MUI_PAGE_DIRECTORY + +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_RUN +!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun +!insertmacro MUI_PAGE_FINISH \ No newline at end of file diff --git a/misc/nsis/mkunlist.cmd b/misc/nsis/mkunlist.cmd new file mode 100755 index 000000000..114116e23 --- /dev/null +++ b/misc/nsis/mkunlist.cmd @@ -0,0 +1,45 @@ +@echo off + +rem This is called from qutebrowser NSIS script at compile time. +rem It enumerates the files of the release and generates a nsh file with the +rem commands to remove them. + +setlocal EnableDelayedExpansion + +if [%2]==[] exit 1 + +set "DIST=%~f1" +set "ULIST=%2" +set "DLIST=%TEMP%\%~n2%RANDOM%.tmp" + +if not exist "%DIST%" exit 2 + +if exist "%ULIST%" del "%ULIST%" || exit 3 +if exist "%DLIST%" del "%DLIST%" || exit 3 + +for /r "%DIST%" %%i in (*) do ( + set "FN=%%i" + set "FN=!FN:%DIST%=!" + set "FN=!FN:$=$$!" + (echo:Delete "$INSTDIR!FN!") >> "%ULIST%" +) + +rem '*' doesn't catch hidden files and there are a couple files starting with +rem a '.', which will appear as hidden if mapped from a linux file system. +for /f "tokens=*" %%i in ('dir "%DIST%" /a:h-d /b /s') do ( + set "HFN=%%i" + set "HFN=!HFN:%DIST%=!" + set "HFN=!HFN:$=$$!" + (echo:Delete "$INSTDIR!HFN!") >> "%ULIST%" +) + +for /r "%DIST%" %%i in (.) do ( + set "DN=%%i" + set "DN=!DN:%DIST%=!" + set "DN=!DN:$=$$!" + (echo:RMDir "$INSTDIR!DN:~0,-1!") >> "%DLIST%" +) + +sort /r "%DLIST%" >> "%ULIST%" + +del "%DLIST%" diff --git a/misc/nsis/qutebrowser.nsi b/misc/nsis/qutebrowser.nsi new file mode 100755 index 000000000..a114e6774 --- /dev/null +++ b/misc/nsis/qutebrowser.nsi @@ -0,0 +1,179 @@ +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +# NSIS installer script. Uses NsisMultiUser plugin and contains portions of +# its demo code, copyright 2017 Richard Drizin, Alex Mitev. + +# Includes modified graphics from the NSIS distribution. + +# Requires: +# - NsisMultiUser plugin @ 79914db https://github.com/Drizin/NsisMultiUser +# - UAC plugin v2.4.5c (20150526) http://nsis.sourceforge.net/UAC_plug-in + + +; Installer Attributes +Unicode true +XPStyle on +ManifestSupportedOS all +SetDatablockOptimize on +SetCompressor /SOLID /FINAL lzma +SetCompressorDictSize 32 +CRCCheck force +AllowSkipFiles off +SetOverwrite on +ShowInstDetails hide +ShowUninstDetails hide + +!addplugindir /x86-unicode ".\Plugins\x86-unicode" +!addincludedir ".\Include" + +!include MUI2.nsh +!include NsisMultiUser.nsh + +; Installer defines +!define PRODUCT_NAME "qutebrowser" ; name of the application as displayed to the user +!define PROGEXE "qutebrowser.exe" ; main application filename +!define COMPANY_NAME "qutebrowser.org" ; company, used for registry tree hierarchy +!define COPYRIGHT "© 2014-2018 Florian Bruhin (The Compiler)" +!define TM "qutebrowser is free software under the GNU General Public License" +!define URL_ABOUT "https://qutebrowser.org/" +!define URL_UPDATE "https://qutebrowser.org/doc/install.html" +!define HELP_LINK "https://qutebrowser.org/doc/help/" +!define CONTACT "mail@qutebrowser.org" +!define COMMENTS "A keyboard-driven, vim-like browser based on PyQt5." +!define SHELL_PROPERTIES "qute://settings/" +!define SHELL_SAFEMODE "--temp-basedir" +!define LANGID "1033" +!define MIN_WIN_VER "XP" +!define SETUP_MUTEX "${PRODUCT_NAME} Setup Mutex" ; do not change this between program versions! +!define APP_MUTEX "${PRODUCT_NAME} App Mutex" ; do not change this between program versions! +!define REG_UN "Software\Microsoft\Windows\CurrentVersion\Uninstall" +!define SETTINGS_REG_KEY "${REG_UN}\${PRODUCT_NAME}" +!define CONFIG_DIR "$APPDATA\${PRODUCT_NAME}" +!define CACHE_DIR "$LOCALAPPDATA\${PRODUCT_NAME}" +!define LICENSE_FILE ".\..\..\LICENSE" +!define MUI_ICON ".\graphics\install.ico" +!define MUI_UNICON ".\graphics\uninstall.ico" +!define MUI_WELCOMEFINISHPAGE_BITMAP ".\graphics\wizard.bmp" +; The old MSI installers had a different Product Code on every release by mistake +!define MSI_COUNT 24 +!define MSI32_010 "{50691080-E51F-4F1A-AEEA-ACA8C64DB98B}" +!define MSI32_011 "{B6FE0FC1-3754-4FF6-A5E5-A305B1EDC8CB}" +!define MSI32_012 "{B1341894-8D82-40C6-B0D0-A5ECEFB997BE}" +!define MSI32_013 "{22EEF3C7-4D72-4F7E-B35B-1F2A22B5E64A}" +!define MSI32_014 "{29C7D770-EBFE-465A-8354-C6A4EA3D8BAF}" +!define MSI32_020 "{061B339B-ABBC-4D89-BE0D-A843FEA48DA7}" +!define MSI32_021 "{0228BB7C-8D7C-4763-A1C6-AAE0B1902AF9}" +!define MSI32_030 "{F514C234-DB31-4158-9D96-53412B431F81}" +!define MSI32_040 "{895E71DC-41D6-4FC3-A0F8-2EC5FE19ACB8}" +!define MSI32_041 "{66F9576D-0DB5-475D-9C25-E0511580C897}" +!define MSI32_050 "{EDB54F4D-7A00-47AE-9808-E59FF5E79136}" +!define MSI32_051 "{EEF03487-BC9F-4EA4-A5A1-E9CF5F9E1FB6}" +!define MSI32_060 "{F9FECA24-95DA-4E46-83E3-A805E5B1CE06}" +!define MSI32_061 "{F1A0F4B9-CCA3-4B07-8ADB-16BC81530440}" +!define MSI32_062 "{43F5E4C5-FF96-4676-B027-5AD63D3871AB}" +!define MSI32_070 "{558FF39C-CA5F-4E2A-87D2-90963FCBC424}" +!define MSI32_080 "{9DF540E2-4F8C-46A4-A27F-43BD0558CC42}" +!define MSI32_081 "{EA0FB6B1-83AF-4F16-8B89-645B587D90FD}" +!define MSI32_082 "{F849A0B2-301C-435D-9CC0-9651938FCA6F}" +!define MSI32_084 "{9331D947-AC86-4542-A755-A833429C6E69}" +!define MSI32_090 "{AD967987-7777-4095-A03A-3F2EE8968D9E}" +!define MSI32_091 "{87F05B8A-2238-4D86-82BB-EC8B4CE97E78}" +!define MSI32_100 "{07B85A0B-D025-4B4B-B46D-BC9B02912835}" +!define MSI32_101 "{9F05D9E4-D049-445E-A489-A7DC0256C774}" +!define MSI64_010 "{A8191862-28A7-4BB0-9532-49AD5CFFFE66}" +!define MSI64_011 "{1C476CC1-A171-48B7-A883-0F00F4D301D3}" +!define MSI64_012 "{ADA727AC-9DDD-4F03-93B7-BAFE950757BE}" +!define MSI64_013 "{64949BFF-287A-4C16-A5F3-84A38A6703F1}" +!define MSI64_014 "{63F22761-D886-4FDD-93F4-7543265E9FF7}" +!define MSI64_020 "{80BE09C6-347F-4121-98D3-1E4363C3CE6B}" +!define MSI64_021 "{2D86F472-DD52-40A1-8FE0-90550D674554}" +!define MSI64_030 "{53DED10D-C609-406F-959E-C1B52A518561}" +!define MSI64_040 "{B9535FDF-7A9E-4AED-BA1E-BEE5FFCBC311}" +!define MSI64_041 "{DAE1309A-FE7D-46E5-B488-B437CC509DF9}" +!define MSI64_050 "{DC9ECE64-F8E5-4BCB-BCFF-BE4ADCEF2655}" +!define MSI64_051 "{26AED286-23BD-49FF-BD9C-7C0DC4467BD7}" +!define MSI64_060 "{3035744D-2390-4D5E-ACAD-905E72B9EBEC}" +!define MSI64_061 "{0223F48F-93A8-4985-BCFF-328E5A9D97D5}" +!define MSI64_062 "{95835A82-A9C2-4924-87DF-E03D910E3400}" +!define MSI64_070 "{61D1AC75-7ECD-45FF-B42B-454C056DB178}" +!define MSI64_080 "{92D1C65C-1338-4B11-B515-6BD5B1FF92D9}" +!define MSI64_081 "{AF7AC009-FB82-48F6-9439-6E46AEB60DBF}" +!define MSI64_082 "{CC316D68-5742-4C2B-98EC-4ADF06A19B84}" +!define MSI64_084 "{633F41F9-FE9B-42D1-9CC4-718CBD01EE11}" +!define MSI64_090 "{5E3E7404-D6D7-4FF1-846A-F9BBFE2F841A}" +!define MSI64_091 "{3190D3F6-7B24-47DC-88E7-99280905FACF}" +!define MSI64_100 "{7AA6530C-3812-4DC5-9A30-E762BBDDF55E}" +!define MSI64_101 "{B0104B85-8229-49FB-8606-275A90ACC024}" + +; Set PLATFORM - default x64 +!ifdef X86 + !define PLATFORM "Win32" + !define ARCH "x86" + !define SUFFIX "win32" +!else + !define PLATFORM "Win64" + !define ARCH "x64" + !define SUFFIX "amd64" +!endif + +; If not defined, get VERSION from PROGEXE. Set DIST_DIR accordingly. +!ifndef VERSION + !define /ifndef DIST_DIR ".\..\..\dist\${PRODUCT_NAME}-${ARCH}" + !getdllversion "${DIST_DIR}\${PROGEXE}" expv_ + !define VERSION "${expv_1}.${expv_2}.${expv_3}" +!else + !define /ifndef DIST_DIR ".\..\..\dist\${PRODUCT_NAME}-${VERSION}-${ARCH}" +!endif + +; Pack the exe header with upx, unless NOUPX is defined. +!ifndef NOUPX + !define /ifndef UPX "upx" ; assume upx is in path if UPX is not defined + !packhdr "$%TEMP%\exehead.tmp" '"${UPX}" "--ultra-brute" "$%TEMP%\exehead.tmp"' +!else + !ifdef UPX + !error "Both UPX and NOUPX are defined." + !endif +!endif + +; Version Information +VIFileVersion "${VERSION}.0" +VIProductVersion "${VERSION}.0" +VIAddVersionKey /LANG=${LANGID} "Comments" "Built with NSIS ${NSIS_VERSION}" +VIAddVersionKey /LANG=${LANGID} "CompanyName" "${COMPANY_NAME}" +VIAddVersionKey /LANG=${LANGID} "FileVersion" "${VERSION}" +VIAddVersionKey /LANG=${LANGID} "InternalName" "${PRODUCT_NAME}-${VERSION}-${SUFFIX}" +VIAddVersionKey /LANG=${LANGID} "LegalTrademarks" "${TM}" +VIAddVersionKey /LANG=${LANGID} "LegalCopyright" "${COPYRIGHT}" +VIAddVersionKey /LANG=${LANGID} "FileDescription" "${PRODUCT_NAME} ${ARCH} Setup" +VIAddVersionKey /LANG=${LANGID} "OriginalFilename" "${PRODUCT_NAME}-${VERSION}-${SUFFIX}.exe" +VIAddVersionKey /LANG=${LANGID} "ProductName" "${PRODUCT_NAME}" +VIAddVersionKey /LANG=${LANGID} "ProductVersion" "${VERSION}" + +; Final Attributes +Name "${PRODUCT_NAME}" +BrandingText "${PRODUCT_NAME} v${VERSION} Installer (${ARCH})" +OutFile "${DIST_DIR}\..\${PRODUCT_NAME}-${VERSION}-${SUFFIX}.exe" + +; installer/uninstaller pages and actions +!include "Utils.nsh" +!include "install_pages.nsh" +; remove next line if you're using signing after the uninstaller is extracted from the initially compiled setup +!include "uninstall_pages.nsh" +!include "install.nsh" +; remove next line if you're using signing after the uninstaller is extracted from the initially compiled setup +!include "uninstall.nsh" diff --git a/misc/nsis/uninstall.nsh b/misc/nsis/uninstall.nsh new file mode 100755 index 000000000..19abc1298 --- /dev/null +++ b/misc/nsis/uninstall.nsh @@ -0,0 +1,174 @@ +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +# NSIS uninstaller header. Uses NsisMultiUser plugin and contains portions of +# its demo code, copyright 2017 Richard Drizin, Alex Mitev. + + +; Variables +Var SemiSilentMode ; installer started uninstaller in semi-silent mode using /SS parameter +Var RunningFromInstaller ; installer started uninstaller using /uninstall parameter + +!insertmacro DeleteRetryAbortFunc "un." +!insertmacro CheckSingleInstanceFunc "un." + +Section "un.Program Files" SectionUninstallProgram + SectionIn RO + + ; Call shell script to generate an uninstall-list nsh file + !tempfile UNLIST + !ifdef NSIS_WIN32_MAKENSIS + !execute 'cmd.exe /c .\mkunlist.cmd "${DIST_DIR}" "${UNLIST}"' + !else + !error "POSIX script for uninstall list generation is not yet available." + !endif + + ; Try to delete the EXE as the first step - if it's in use, don't remove anything else + !insertmacro DeleteRetryAbort "$INSTDIR\${PROGEXE}" + + ; Include and then delete the uninstall nsh file + !include "${UNLIST}" + !delfile "${UNLIST}" + + ; Clean up "Dektop Icon" + !insertmacro MULTIUSER_GetCurrentUserString $0 + !insertmacro DeleteRetryAbort "$DESKTOP\${PRODUCT_NAME}$0.lnk" + + ; Clean up "Start Menu Icon" + !insertmacro MULTIUSER_GetCurrentUserString $0 + !insertmacro DeleteRetryAbort "$STARTMENU\${PRODUCT_NAME}$0.lnk" + + ; Clean up Windows Registry + ${if} $MultiUser.InstallMode == "AllUsers" + ${orif} ${AtLeastWin8} + DeleteRegValue SHCTX "Software\RegisteredApplications" "${PRODUCT_NAME}" + DeleteRegKey SHCTX "Software\Clients\StartMenuInternet\${PRODUCT_NAME}" + DeleteRegKey SHCTX "Software\Classes\${PRODUCT_NAME}HTML" + DeleteRegKey SHCTX "Software\Classes\${PRODUCT_NAME}URL" + DeleteRegValue SHCTX "Software\Classes\.htm\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.html\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.shtml\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.svg\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.xht\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.xhtml\OpenWithProgids" "${PRODUCT_NAME}HTML" + DeleteRegValue SHCTX "Software\Classes\.webp\OpenWithProgids" "${PRODUCT_NAME}HTML" + ${endif} + + ; Refresh Shell Icons + System::Call "shell32::SHChangeNotify(i 0x08000000, i 0, i 0, i 0)" +SectionEnd + +Section /o "!un.Program Settings" SectionRemoveSettings + ; this section is executed only explicitly and shouldn't be placed in SectionUninstallProgram + DeleteRegKey HKCU "Software\${PRODUCT_NAME}" + SetShellVarContext current + RMDIR /r "${CONFIG_DIR}\data" + RMDIR /r "${CONFIG_DIR}\config" + RMDIR "${CONFIG_DIR}" + ${if} $MultiUser.InstallMode == "AllUsers" + SetShellVarContext all + ${endif} +SectionEnd + +Section /o "un.Program Cache" SectionRemoveCache + ; this section is executed only explicitly and shouldn't be placed in SectionUninstallProgram + SetShellVarContext current + RMDIR /r "${CACHE_DIR}\cache" + RMDIR "${CACHE_DIR}" + ${if} $MultiUser.InstallMode == "AllUsers" + SetShellVarContext all + ${endif} + +SectionEnd + +Section "-Uninstall" ; hidden section, must always be the last one! + Delete "$INSTDIR\${UNINSTALL_FILENAME}" ; we cannot use DeleteRetryAbort here - when using the _? parameter the uninstaller cannot delete itself and Delete fails, which is OK + ; remove the directory only if it is empty - the user might have saved some files in it + RMDir "$INSTDIR" + + ; Remove the uninstaller from registry as the very last step - if sth. goes wrong, let the user run it again + !insertmacro MULTIUSER_RegistryRemoveInstallInfo ; Remove registry keys +SectionEnd + +; Modern install component descriptions +!insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SectionUninstallProgram} "Remove ${PRODUCT_NAME} application files." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionRemoveSettings} "Remove ${PRODUCT_NAME} user files (configuration, bookmarks, history, sessions, scripts, cookies, etc.)." + !insertmacro MUI_DESCRIPTION_TEXT ${SectionRemoveCache} "Remove ${PRODUCT_NAME} cache files." +!insertmacro MUI_UNFUNCTION_DESCRIPTION_END + +; Callbacks +Function un.onInit + ${GetParameters} $R0 + + ${GetOptions} $R0 "/uninstall" $R1 + ${ifnot} ${errors} + StrCpy $RunningFromInstaller 1 + ${else} + StrCpy $RunningFromInstaller 0 + ${endif} + + var /GLOBAL KeepReg + ${GetOptions} $R0 "/upgrade" $R1 + ${ifnot} ${errors} + StrCpy $KeepReg 1 + ${else} + StrCpy $KeepReg 0 + ${endif} + + ${GetOptions} $R0 "/SS" $R1 + ${ifnot} ${errors} + StrCpy $SemiSilentMode 1 + StrCpy $RunningFromInstaller 1 + SetAutoClose true ; auto close (if no errors) if we are called from the installer; if there are errors, will be automatically set to false + ${else} + StrCpy $SemiSilentMode 0 + ${endif} + + ${ifnot} ${UAC_IsInnerInstance} + ${andif} $RunningFromInstaller = 0 + !insertmacro CheckSingleInstance "Setup" "Global" "${SETUP_MUTEX}" + !insertmacro CheckSingleInstance "Application" "Local" "${APP_MUTEX}" + ${endif} + + !insertmacro MULTIUSER_UNINIT + + !insertmacro MUI_UNGETLANGUAGE +FunctionEnd + +Function un.PageInstallModeChangeMode +FunctionEnd + +Function un.PageComponentsPre + ${if} $SemiSilentMode = 1 + Abort ; if user is installing, no use to remove program settings anyway (should be compatible with all versions) + ${endif} +FunctionEnd + +Function un.PageComponentsShow + ; Show/hide the Back button + GetDlgItem $0 $HWNDPARENT 3 + ShowWindow $0 $UninstallShowBackButton +FunctionEnd + +Function un.onUninstFailed + ${if} $SemiSilentMode = 0 + MessageBox MB_ICONSTOP "${PRODUCT_NAME} ${VERSION} could not be fully uninstalled.$\r$\nPlease, restart Windows and run the uninstaller again." /SD IDOK + ${else} + MessageBox MB_ICONSTOP "${PRODUCT_NAME} could not be fully installed.$\r$\nPlease, restart Windows and run the setup program again." /SD IDOK + ${endif} +FunctionEnd diff --git a/misc/nsis/uninstall_pages.nsh b/misc/nsis/uninstall_pages.nsh new file mode 100755 index 000000000..8ad203ebb --- /dev/null +++ b/misc/nsis/uninstall_pages.nsh @@ -0,0 +1,32 @@ +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +# NSIS pages header. Uses NsisMultiUser plugin and contains portions of +# its demo code, copyright 2017 Richard Drizin, Alex Mitev. + + +; Pages +!define MUI_UNABORTWARNING ; Show a confirmation when cancelling the installation + +!define MULTIUSER_INSTALLMODE_CHANGE_MODE_FUNCTION un.PageInstallModeChangeMode +!insertmacro MULTIUSER_UNPAGE_INSTALLMODE + +!define MUI_PAGE_CUSTOMFUNCTION_PRE un.PageComponentsPre +!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.PageComponentsShow +!insertmacro MUI_UNPAGE_COMPONENTS + +!insertmacro MUI_UNPAGE_INSTFILES diff --git a/misc/qutebrowser.nsi b/misc/qutebrowser.nsi deleted file mode 100644 index 76f459a78..000000000 --- a/misc/qutebrowser.nsi +++ /dev/null @@ -1,80 +0,0 @@ -Name "qutebrowser" - -Unicode true -RequestExecutionLevel admin -SetCompressor /solid lzma - -!ifdef X64 - OutFile "..\dist\qutebrowser-${VERSION}-amd64.exe" - InstallDir "$ProgramFiles64\qutebrowser" -!else - OutFile "..\dist\qutebrowser-${VERSION}-win32.exe" - InstallDir "$ProgramFiles\qutebrowser" -!endif - -;Default installation folder - -!include "MUI2.nsh" -;!include "MultiUser.nsh" - -!define MUI_ABORTWARNING -;!define MULTIUSER_MUI -;!define MULTIUSER_INSTALLMODE_COMMANDLINE -!define MUI_ICON "../icons/qutebrowser.ico" -!define MUI_UNICON "../icons/qutebrowser.ico" - -!insertmacro MUI_PAGE_LICENSE "..\LICENSE" -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -!insertmacro MUI_LANGUAGE "English" - -; depends on admin status -;SetShellVarContext current - - -Section "Install" - - ; Uninstall old versions - ExecWait 'MsiExec.exe /quiet /qn /norestart /X{633F41F9-FE9B-42D1-9CC4-718CBD01EE11}' - ExecWait 'MsiExec.exe /quiet /qn /norestart /X{9331D947-AC86-4542-A755-A833429C6E69}' - IfFileExists "$INSTDIR\uninst.exe" 0 +2 - ExecWait "$INSTDIR\uninst.exe /S _?=$INSTDIR" - CreateDirectory "$INSTDIR" - - SetOutPath "$INSTDIR" - - !ifdef X64 - file /r "..\dist\qutebrowser-${VERSION}-x64\*.*" - !else - file /r "..\dist\qutebrowser-${VERSION}-x86\*.*" - !endif - - SetShellVarContext all - CreateShortCut "$SMPROGRAMS\qutebrowser.lnk" "$INSTDIR\qutebrowser.exe" - - ;Create uninstaller - WriteUninstaller "$INSTDIR\uninst.exe" - - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "DisplayName" "qutebrowser" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "UninstallString" '"$INSTDIR\uninst.exe"' - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "QuietUninstallString" '"$INSTDIR\uninst.exe" /S' - -SectionEnd - -;-------------------------------- -;Uninstaller Section - -Section "Uninstall" - - SetShellVarContext all - Delete "$SMPROGRAMS\qutebrowser.lnk" - - RMDir /r "$INSTDIR\*.*" - RMDir "$INSTDIR" - - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" - -SectionEnd