-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- removed dependancy from MUI2.nsh, now plugin can be used in any UI - added support for Ultra Modern UI, MUI 1 and NSIS native interface, fixed positioning of elements - added fully functional demos for all supported interfaces - full update of the documentation - support for the /uninstall parameter - always display page in installer (no elevation in the beginning), even if /allusers or /currentuser parameters are passed Other changes: - removed MUI_DEFAULT macro - COMPANY_NAME define is not required - rename InstallHidePagesBeforeComponents to InstallShowPagesBeforeComponents, UninstallHideBackButton to UninstallShowBackButton - removed MULTIUSER_INSTALLMODE_PROGRAMFILES, use MULTIUSER_INSTALLMODE_64_BIT instead (calls SetRegView 64 to avoid WOW6432Node registry redirection) - renamed HasTwoAvailableOptions to PerMachineOptionAvailable - new variables HasCurrentModeInstallation, PerMachineUninstallString, PerUserUninstallString - removed UAC_IsAdmin calls and used existing $IsAdmin variable instead - reduced UAC_IsInnerInstance calls via the new $IsInnerInstance variable - renamed CheckElevationRequired to CheckPageElevationRequired, called it from InstallModeLeave and SetShieldAndTexts to reduce code - proper elevation when /currentuser parameter is passed
- Loading branch information
1 parent
f379e4b
commit 0226b2f
Showing
36 changed files
with
2,514 additions
and
488 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
!include LogicLib.nsh | ||
!include x64.nsh | ||
|
||
!define ERROR_ALREADY_EXISTS 0x000000b7 | ||
!define ERROR_ACCESS_DENIED 0x5 | ||
|
||
!macro CheckPlatform PLATFORM | ||
${if} ${RunningX64} | ||
!if ${PLATFORM} == "Win32" | ||
MessageBox MB_ICONSTOP "Please, run the 64-bit installer of ${PRODUCT_NAME} on this version of Windows." /SD IDOK | ||
Quit ; will SetErrorLevel 2 - Installation aborted by script | ||
!endif | ||
${else} | ||
!if ${PLATFORM} == "Win64" | ||
MessageBox MB_ICONSTOP "Please, run the 32-bit installer of ${PRODUCT_NAME} on this version of Windows." /SD IDOK | ||
Quit ; will SetErrorLevel 2 - Installation aborted by script | ||
!endif | ||
${endif} | ||
!macroend | ||
|
||
!macro CheckMinWinVer MIN_WIN_VER | ||
${ifnot} ${AtLeastWin${MIN_WIN_VER}} | ||
MessageBox MB_ICONSTOP "This program requires at least Windows ${MIN_WIN_VER}." /SD IDOK | ||
Quit ; will SetErrorLevel 2 - Installation aborted by script | ||
${endif} | ||
!macroend | ||
|
||
!macro CheckSingleInstance SINGLE_INSTANCE_ID | ||
System::Call 'kernel32::CreateMutex(i 0, i 0, t "Global\${SINGLE_INSTANCE_ID}") i .r0 ?e' | ||
Pop $1 ; the stack contains the result of GetLastError | ||
${if} $1 = "${ERROR_ALREADY_EXISTS}" | ||
${orif} $1 = "${ERROR_ACCESS_DENIED}" ; ERROR_ACCESS_DENIED means the mutex was created by another user and we don't have access to open it, so application is running | ||
System::Call 'kernel32::CloseHandle(i $0)' ; if the user closes the already running instance, allow to start a new one without closing the MessageBox | ||
|
||
; will display NSIS taskbar button, no way to hide it before GUIInit, $HWNDPARENT is 0 | ||
MessageBox MB_ICONSTOP "The setup of ${PRODUCT_NAME} is already running." /SD IDOK | ||
|
||
Quit ; will SetErrorLevel 2 - Installation aborted by script | ||
${endif} | ||
!macroend | ||
|
||
Function un.DeleteRetryAbort | ||
; unlike the File instruction, Delete doesn't abort (un)installation on error - it just sets the error flag and skips the file as if nothing happened | ||
try: | ||
ClearErrors | ||
Delete "$0" | ||
${if} ${errors} | ||
MessageBox MB_RETRYCANCEL|MB_ICONSTOP "Error deleting file:$\r$\n$\r$\n$0$\r$\n$\r$\nClick Retry to try again, or$\r$\nCancel to stop the uninstall." /SD IDCANCEL IDRETRY try | ||
Abort "Error deleting file $0" ; when called from section, will SetErrorLevel 2 - Installation aborted by script | ||
${endif} | ||
FunctionEnd | ||
|
||
!macro un.DeleteRetryAbort filename | ||
StrCpy $0 "${filename}" | ||
Call un.DeleteRetryAbort | ||
!macroend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
!addplugindir /x86-ansi ".\..\..\Plugins\x86-ansi" | ||
!addplugindir /x86-unicode ".\..\..\Plugins\x86-unicode" | ||
!addincludedir ".\..\..\Include" | ||
|
||
!include MUI2.nsh | ||
!include UAC.nsh | ||
!include NsisMultiUser.nsh | ||
!include LogicLib.nsh | ||
!include ".\..\Common\Utils.nsh" | ||
|
||
!define PRODUCT_NAME "NsisMultiUser MUI2 Limited Demo" ; name of the application as displayed to the user | ||
!define VERSION "1.0" ; main version of the application (may be 0.1, alpha, beta, etc.) | ||
!define PROGEXE "calc.exe" ; main application filename | ||
!define COMPANY_NAME "Alex Mitev" ; company, used for registry tree hierarchy | ||
!define PLATFORM "Win64" | ||
!define MIN_WIN_VER "XP" | ||
!define SINGLE_INSTANCE_ID "${COMPANY_NAME} ${PRODUCT_NAME} Unique ID" ; do not change this between program versions! | ||
!define LICENSE_FILE "License.txt" ; license file, optional | ||
|
||
; NsisMultiUser optional defines | ||
!define MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS 1 ; value 0 is not supported - previous installation is not fully removed | ||
!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} ${PLATFORM}" | ||
|
||
Var StartMenuFolder | ||
|
||
; Installer Attributes | ||
Name "${PRODUCT_NAME} ${VERSION} ${PLATFORM}" | ||
OutFile "Setup_MUI2_Limited.exe" | ||
BrandingText "©2017 ${COMPANY_NAME}" | ||
|
||
AllowSkipFiles off | ||
SetOverwrite on ; (default setting) set to on except for where it is manually switched off | ||
ShowInstDetails show | ||
SetCompressor /SOLID lzma | ||
|
||
; Pages | ||
!define MUI_ABORTWARNING ; Show a confirmation when cancelling the installation | ||
|
||
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomeLicensePre | ||
!insertmacro MUI_PAGE_WELCOME | ||
|
||
!ifdef LICENSE_FILE | ||
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomeLicensePre | ||
!insertmacro MUI_PAGE_LICENSE ".\..\..\${LICENSE_FILE}" | ||
!endif | ||
|
||
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomeLicensePre | ||
!insertmacro MUI_PAGE_LICENSE "readme.txt" | ||
|
||
!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 | ||
|
||
!define MUI_STARTMENUPAGE_NODISABLE ; Do not display the checkbox to disable the creation of Start Menu shortcuts | ||
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${PRODUCT_NAME}" | ||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" ; writing to $StartMenuFolder happens in MUI_STARTMENU_WRITE_END, so it's safe to use "SHCTX" here | ||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" | ||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "StartMenuFolder" | ||
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageStartMenuPre | ||
!insertmacro MUI_PAGE_STARTMENU "" "$StartMenuFolder" | ||
|
||
!insertmacro MUI_PAGE_INSTFILES | ||
|
||
!define MUI_FINISHPAGE_RUN | ||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun | ||
!insertmacro MUI_PAGE_FINISH | ||
|
||
!include Uninstall.nsh | ||
|
||
!insertmacro MUI_LANGUAGE "English" ; Set languages (first is default language) - must be inserted after all pages | ||
|
||
InstType "Typical" | ||
InstType "Minimal" | ||
InstType "Full" | ||
|
||
Section "Core Files (required)" SectionCoreFiles | ||
SectionIn 1 2 3 RO | ||
|
||
${if} $HasCurrentModeInstallation == 1 ; if there's an installed version, remove all optinal components (except "Core Files") | ||
; Clean up "Documentation" | ||
Delete "$INSTDIR\readme.txt" | ||
|
||
; Clean up "Program Group" - we check that we created Start menu folder, if $StartMenuFolder is empty, the whole $SMPROGRAMS directory will be removed! | ||
${if} "$StartMenuFolder" != "" | ||
RMDir /r "$SMPROGRAMS\$StartMenuFolder" | ||
${endif} | ||
|
||
; Clean up "Dektop Icon" | ||
Delete "$DESKTOP\${PRODUCT_NAME}.lnk" | ||
|
||
; Clean up "Start Menu Icon" | ||
Delete "$STARTMENU\${PRODUCT_NAME}.lnk" | ||
|
||
; Clean up "Quick Launch Icon" | ||
Delete "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" | ||
${endif} | ||
|
||
SetOutPath $INSTDIR | ||
; Write uninstaller and registry uninstall info as the first step, | ||
; so that the user has the option to run the uninstaller if sth. goes wrong | ||
WriteUninstaller "${UNINSTALL_FILENAME}" | ||
!insertmacro MULTIUSER_RegistryAddInstallInfo ; add registry keys | ||
|
||
File "C:\Windows\System32\${PROGEXE}" | ||
!ifdef LICENSE_FILE | ||
File ".\..\..\${LICENSE_FILE}" | ||
!endif | ||
SectionEnd | ||
|
||
Section "Documentation" SectionDocumentation | ||
SectionIn 1 3 | ||
|
||
SetOutPath $INSTDIR | ||
File "readme.txt" | ||
|
||
SectionEnd | ||
|
||
SectionGroup /e "Integration" SectionGroupIntegration | ||
|
||
Section "Program Group" SectionProgramGroup | ||
SectionIn 1 3 | ||
|
||
!insertmacro MUI_STARTMENU_WRITE_BEGIN "" | ||
|
||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder" | ||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${PRODUCT_NAME}.lnk" "$INSTDIR\${PROGEXE}" | ||
|
||
!ifdef LICENSE_FILE | ||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\License Agreement.lnk" "$INSTDIR\${LICENSE_FILE}" | ||
!endif | ||
${if} $MultiUser.InstallMode == "AllUsers" | ||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\${UNINSTALL_FILENAME}" "/allusers" | ||
${else} | ||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall (current user).lnk" "$INSTDIR\${UNINSTALL_FILENAME}" "/currentuser" | ||
${endif} | ||
|
||
!insertmacro MUI_STARTMENU_WRITE_END | ||
SectionEnd | ||
|
||
Section "Dektop Icon" SectionDesktopIcon | ||
SectionIn 1 3 | ||
|
||
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PROGEXE}" | ||
SectionEnd | ||
|
||
Section /o "Start Menu Icon" SectionStartMenuIcon | ||
SectionIn 3 | ||
|
||
CreateShortCut "$STARTMENU\${PRODUCT_NAME}.lnk" "$INSTDIR\${PROGEXE}" | ||
SectionEnd | ||
|
||
Section /o "Quick Launch" SectionQuickLaunchIcon | ||
SectionIn 3 | ||
|
||
; The QuickLaunch is always only for the current user | ||
CreateShortCut "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" "$INSTDIR\${PROGEXE}" | ||
SectionEnd | ||
SectionGroupEnd | ||
|
||
; Modern install component descriptions | ||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN | ||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionCoreFiles} "Core files requred to run ${PRODUCT_NAME}." | ||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionDocumentation} "Help files for ${PRODUCT_NAME}." | ||
|
||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionGroupIntegration} "Select how to integrate the program in Windows." | ||
!insertmacro MUI_DESCRIPTION_TEXT ${SectionProgramGroup} "Create a ${PRODUCT_NAME} program group under Start Menu->Programs." | ||
!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_DESCRIPTION_TEXT ${SectionQuickLaunchIcon} "Create ${PRODUCT_NAME} icon in Quick Launch." | ||
!insertmacro MUI_FUNCTION_DESCRIPTION_END | ||
|
||
; Callbacks | ||
Function .onInit | ||
!insertmacro CheckPlatform ${PLATFORM} | ||
!insertmacro CheckMinWinVer ${MIN_WIN_VER} | ||
${ifnot} ${UAC_IsInnerInstance} | ||
!insertmacro CheckSingleInstance "${SINGLE_INSTANCE_ID}" | ||
${endif} | ||
|
||
!insertmacro MULTIUSER_INIT | ||
FunctionEnd | ||
|
||
Function PageWelcomeLicensePre | ||
${if} $InstallShowPagesBeforeComponents == 0 | ||
Abort ; don't display the Welcome and License pages for the inner instance | ||
${endif} | ||
FunctionEnd | ||
|
||
Function PageInstallModeChangeMode | ||
!insertmacro MUI_STARTMENU_GETFOLDER "" $StartMenuFolder | ||
FunctionEnd | ||
|
||
Function PageDirectoryPre | ||
GetDlgItem $0 $HWNDPARENT 1 | ||
${if} ${SectionIsSelected} ${SectionProgramGroup} | ||
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^NextBtn)" ; this is not the last page before installing | ||
${else} | ||
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^InstallBtn)" ; this is the last page before installing | ||
${endif} | ||
FunctionEnd | ||
|
||
Function PageDirectoryShow | ||
${if} $CmdLineDir != "" | ||
${orif} $HasCurrentModeInstallation == 1 | ||
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 PageStartMenuPre | ||
${ifnot} ${SectionIsSelected} ${SectionProgramGroup} | ||
Abort ; don't display this dialog if SectionProgramGroup is not selected | ||
${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 | ||
|
Oops, something went wrong.