I have two license page and in the second license page, if user choose not to install the 3rd party app, it will show finish page. So far I use MUI_CUSTOMFUNCTION_ABORT onUserAbort to move into finish page.
But the problem is when user click Skip button (it's actually Cancel button and I rename it into Skip), it will stay on license page and the Install button change to Next button (image 1 -> image 2 -> image 3). I know this is happen because I call Abort in onUserAbort. If I don't call Abort, then the window will automatically close when user click Skip.
Do you have any idea how to directly move to finish page? (image 1 -> image 3, without image 2)
!insertmacro MUI_PAGE_WELCOME
page custom CheckHWSpecs ShowNotMeetRequirementDialog
!insertmacro MUI_PAGE_LICENSE "${SOURCEFOLDER}\license1.txt"
!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!define MUI_LICENSEPAGE_CHECKBOX
!define MUI_PAGE_CUSTOMFUNCTION_PRE Lic2Pre
!define MUI_PAGE_CUSTOMFUNCTION_SHOW Lic2Show
!insertmacro MUI_PAGE_LICENSE "${SOURCEFOLDER}\license2.txt"
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!define MUI_CUSTOMFUNCTION_ABORT onUserAbort
!insertmacro MUI_LANGUAGE English
The code on Lic2Pre:
Function Lic2Pre
StrCpy $R8 2
FunctionEnd
The code on Lic2Show:
Function Lic2Show
GetDlgItem $0 $hwndparent 2
SendMessage $0 ${WM_SETTEXT} 0 "STR:Skip"
!insertmacro SelectSection ${SEC0013}
!insertmacro UnselectSection ${SEC0000}
!insertmacro UnselectSection ${SEC0002}
!insertmacro UnselectSection ${SEC0003}
!insertmacro UnselectSection ${SEC0004}
!insertmacro UnselectSection ${SEC0005}
!insertmacro UnselectSection ${SEC0007}
!insertmacro UnselectSection ${SEC0010}
!insertmacro UnselectSection ${SEC0011}
!insertmacro UnselectSection ${SEC0012}
FunctionEnd
The code to go into specific page:
Function RelGotoPage
IntCmp $R9 0 0 Move Move
StrCmp $R9 "X" 0 Move
StrCpy $R9 "120"
Move:
SendMessage $HWNDPARENT "0x408" "$R9" ""
FunctionEnd
The custom function on user abort:
Function onUserAbort
StrCmp $R8 2 0 End
StrCpy $R9 2
Call RelGotoPage
Abort
End:
FunctionEnd
!include Sections.nsh
!include WinMessages.nsh
ShowInstDetails show
!define MUI_CUSTOMFUNCTION_ABORT onUserAbort
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Examples\example1.nsi"
!insertmacro MUI_PAGE_INSTFILES
!define MUI_LICENSEPAGE_CHECKBOX
!define MUI_LICENSEPAGE_CHECKBOX_TEXT "Blah blah blah app and agree..."
!define MUI_PAGE_CUSTOMFUNCTION_SHOW Lic2Show
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE Lic2Leave
!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Examples\example2.nsi"
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Section /o "Bonus app" SID_BONUS
DetailPrint "Installing bonus app..."
Sleep 2222
SectionEnd
Section "Main app" SID_MAIN
DetailPrint "Installing main app..."
Sleep 2222
SectionEnd
var installBonus
Function Lic2Show
StrCpy $installBonus 1
GetDlgItem $0 $hwndparent 2
SendMessage $0 ${WM_SETTEXT} 0 "STR:&Skip"
!insertmacro UnselectSection ${SID_MAIN} ; Already installed, uncheck
FunctionEnd
Function Lic2Leave
${If} $installBonus == 1
!insertmacro SelectSection ${SID_BONUS}
${EndIf}
FunctionEnd
Function onUserAbort
${If} $installBonus == 1
StrCpy $installBonus 0
System::Call 'USER32::PostMessage(i$HWNDPARENT,i0x408,i 1,i0)' ; Delayed skip 1 page
Abort
${EndIf}
FunctionEnd
Have a look at the Go to a NSIS page on the Wiki
Related
I am looking for a way so certain components behave like radio buttons, but one of the additional components is selected by default - right after starting the installer.
Unfortunately the main component gets also unselected when choosing other components, and the built-in function .onSelChange ignores the initially selected component.
!include "MUI2.nsh"
!include "Sections.nsh"
OutFile "ABC.exe"
Name "ABC 1.0"
!insertmacro MUI_PAGE_COMPONENTS
Section "!ABC main" SEC_main
SectionEnd
Section /o "ABC expansion 1" SEC_exp1
SectionEnd
Section /o "ABC expansion 2" SEC_exp2
SectionEnd
Section /o "ABC expansion 3" SEC_exp3
SectionEnd
Section /o "ABC expansion 4" SEC_exp4
SectionEnd
Section /o "ABC expansion 5" SEC_exp5
SectionEnd
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${SEC_exp1}
!insertmacro RadioButton ${SEC_exp2}
!insertmacro RadioButton ${SEC_exp3}
!insertmacro RadioButton ${SEC_exp4}
!insertmacro RadioButton ${SEC_exp5}
!insertmacro EndRadioButtons
FunctionEnd
Function .onInit
SectionSetFlags ${SEC_main} 25
SectionSetFlags ${SEC_exp3} 1
FunctionEnd
The solution is to create a variable (in the code below it's $abc_sec_exp_group) that stores the information of the initially selected component.
var abc_sec_exp_group
; ...
Function .onSelChange
!insertmacro StartRadioButtons $abc_sec_exp_group
!insertmacro RadioButton ${SEC_exp1}
!insertmacro RadioButton ${SEC_exp2}
!insertmacro RadioButton ${SEC_exp3}
!insertmacro RadioButton ${SEC_exp4}
!insertmacro RadioButton ${SEC_exp5}
!insertmacro EndRadioButtons
FunctionEnd
Function .onInit
SectionSetFlags ${SEC_main} 25
SectionSetFlags ${SEC_exp3} 1
StrCpy $abc_sec_exp_group ${SEC_exp3} ;<-------;
FunctionEnd
Please note that I have been researching why the above is happening, including studying these links:
NSIS installer .onInit and un.onInit run twice because of UAC
https://github.com/Tribler/tribler/pull/2168
But the above UAC issue does not appear to apply to my case because I am not using that plug-in. Anyways, I am just wondering, why is the entire script running twice? I had meant initially to based it on this example script:
https://nsis.sourceforge.io/Two_installations_in_one_installer
But the script design ended up getting changed a lot, including not requiring the two-layer nested checkboxes.
!include "LogicLib.nsh"
!include "Sections.nsh"
;Include Modern UI
!include "MUI2.nsh"
!define MAJOR_VERSION "1"
!define MINOR_VERSION "2"
!define PATCH_VERSION "3"
!define BUILD_VERSION "4"
!define APP_COPYRIGHT "MyApp © MyCompany 2021"
!define COMPANY_NAME "MyCompany"
!define FLEX_LM "FlexLM"
!define FLEX_DIR "FlexSQI"
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"
BrandingText "${COMPANY_NAME}"
OutFile ${SETUP_NAME}
Icon "favicon.ico"
UninstallIcon "favicon.ico"
!define MUI_ICON "favicon.ico"
!define MUI_UNICON "favicon.ico"
Name "${PRODUCT_NAME}"
InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
InstallDirRegKey HKLM "Software\$PRODUCT_NAME" ""
ShowInstDetails hide
ShowUnInstDetails hide
SetCompressor /SOLID lzma
SetCompressorDictSize 12
;Request application privileges for Windows
RequestExecutionLevel admin
!macro WriteSignedUninstaller Destination
!makensis '"/DGENRATINGUNINST=$%TEMP%\Uninst.exe" "${__FILE__}" "/XOutfile `$%TEMP%\tempinstaller.exe`"' = 0 ; Create fake installer
!system 'set __COMPAT_LAYER=RunAsInvoker&"$%TEMP%\tempinstaller.exe"' = 2 ; Run fake installer to generate the uninstaller
!system 'SIGNTOOL sign /f CodeSigningCertificate/MyCompany.pfx /p Test /tr http://timestamp.digicert.com /td SHA256 "$%TEMP%\Uninst.exe"' = 0 ; Change this line. As a demonstration, use !system 'echo Dummy >> "$%TEMP%\Uninst.exe"'
File "/oname=${Destination}" "$%TEMP%\Uninst.exe"
!macroend
!macro DeclareLanguages
# Define languages that the installer has
!insertmacro MUI_LANGUAGE "English"
!macroend
!ifndef GENRATINGUNINST
Var MyAppInstallDir
Var FlexLmInstallDir
# Installer:
############
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "MyAppLicense.txt"
!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesCheck
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS
## This is the title on the MyApp Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesA
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
## This is the title on the FlexLM Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesB
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE DeleteSectionsINI
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro DeclareLanguages
;--------------------------------
LangString NoSectionsSelected ${LANG_ENGLSH} "You haven't selected any sections!"
LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLSH} "Setup will install \
${FLEX_LM} in the following folder..."
;--------------------------------
; Function
; StrContains
; This function does a case sensitive searches for an occurrence of a substring in a string.
; It returns the substring if it is found.
; Otherwise it returns null("").
; Written by kenglish_hi
; Adapted from StrReplace written by dandaman32
Var STR_HAYSTACK
Var STR_NEEDLE
Var STR_CONTAINS_VAR_1
Var STR_CONTAINS_VAR_2
Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR
Function StrContains
Exch $STR_NEEDLE
Exch 1
Exch $STR_HAYSTACK
; Uncomment to debug
;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
StrCpy $STR_RETURN_VAR ""
StrCpy $STR_CONTAINS_VAR_1 -1
StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
loop:
IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
Goto loop
found:
StrCpy $STR_RETURN_VAR $STR_NEEDLE
Goto done
done:
Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the
Exch $STR_RETURN_VAR
FunctionEnd
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK
Push `${HAYSTACK}`
Push `${NEEDLE}`
Call StrContains
Pop `${OUT}`
!macroend
!define StrContains '!insertmacro "_StrContainsConstructor"'
;--------------------------------
; Start sections
Section "MyApp" SEC1
${StrContains} $0 "MyApp" "$INSTDIR"
StrCmp $0 "" notfoundMyApp
StrCpy $MyAppInstallDir "$INSTDIR"
Goto installMyApp
installMyApp:
##All the files in Group 1 will be installed to the same location, $INSTDIR
SetOutPath "$INSTDIR"
!insertmacro WriteSignedUninstaller "$InstDir\Uninst.exe"
File MyApp.exe
File ReleaseNotes.txt
File MyCompany_LandingPage_114.bmp
File MyAppLicense.txt
# create a shortcut named "new shortcut" in the start menu programs directory
CreateShortcut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" "$InstDir\${PRODUCT_NAME}.exe"
# Add application to registry
ClearErrors
WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'Company Name' "${COMPANY_NAME}"
WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'Version' "${PRODUCT_VERSION}"
WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'AppID' "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
# Add program to Add/Remove programs
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayIcon" "$PROGRAMFILES64\${PRODUCT_NAME}\${PRODUCT_NAME}.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"Publisher" "${COMPANY_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"UninstallString" "$\"$INSTDIR\Uninst.exe$\""
notfoundMyApp:
; Do nothing
SectionEnd
Section /o "FlexLM" SEC3
${StrContains} $0 "Flex" "$INSTDIR"
StrCmp $0 "" notfoundFlex
StrCpy $FlexLmInstallDir "$INSTDIR"
Goto installFlex
installFlex:
##All the files in Group 2 will be installed to the same location, $INSTDIR
SetOutPath "$INSTDIR"
File installs.exe
File lmdown.exe
File lmflex.exe
notfoundFlex:
; Do nothing
SectionEnd
;--------------------------------
; Settings
!define PROG1_InstDir "$PROGRAMFILES64\${PRODUCT_NAME}"
!define PROG1_StartIndex ${SEC1}
!define PROG1_EndIndex ${SEC1}
!define PROG2_InstDir "C:\${FLEX_DIR}\"
!define PROG2_StartIndex ${SEC3}
!define PROG2_EndIndex ${SEC3}
;--------------------------------
;Descriptions
;Language strings
LangString DESC_SecMyApp ${LANG_ENGLISH} "MyAppTM software is an easy-to-use suite of tools."
LangString DESC_SecFlexLM ${LANG_ENGLISH} "FlexSQI contains all the files necessary to implement the FlexLM license server."
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC1} $(DESC_SecMyApp)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC3} $(DESC_SecFlexLM)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
; Please don`t modify below here unless you`re a NSIS 'wiz-kid'
## Create $PLUGINSDIR
Function .onInit
InitPluginsDir
SetOutPath $TEMP
File /oname=spltmp.bmp "MyCompany_LandingPage_114.bmp"
splash::show 2000 $TEMP\spltmp
Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normally, and '-1' if some error occurred.
Delete $TEMP\spltmp.bmp
FunctionEnd
## If user goes back to this page from 1st Directory page
## we need to put the sections back to how they were before
Var IfBack
Function SelectFilesCheck
StrCmp $IfBack 1 0 NoCheck
Call ResetFiles
NoCheck:
FunctionEnd
## Also if no sections are selected, warn the user!
Function ComponentsLeave
Push $R0
Push $R1
Call IsPROG1Selected
Pop $R0
Call IsPROG2Selected
Pop $R1
StrCmp $R0 1 End
StrCmp $R1 1 End
Pop $R1
Pop $R0
MessageBox MB_OK|MB_ICONEXCLAMATION "$(NoSectionsSelected)"
Abort
End:
Pop $R1
Pop $R0
FunctionEnd
Function IsPROG1Selected
Push $R0
StrCpy $R0 ${PROG1_StartIndex} # Group 1 start
SectionGetFlags 0 $R0 # Get section flags
IntOp $R0 $R0 & ${SF_SELECTED}
StrCmp $R0 ${SF_SELECTED} 0 +3 # If section is selected, done
StrCpy $R0 1
Exch $R0
FunctionEnd
Function IsPROG2Selected
Push $R1
StrCpy $R1 ${PROG2_StartIndex} # Group 2 start
IntOp $R1 $R1 + 1
SectionGetFlags 1 $R1 # Get section flags
IntOp $R1 $R1 & ${SF_SELECTED}
StrCmp $R1 ${SF_SELECTED} 0 +3 # If section is selected, done
StrCpy $R1 1
Exch $R1
FunctionEnd
## This will set all sections to how they were on the components page
## originally
Function ResetFiles
Push $R0
Push $R1
StrCpy $R0 ${PROG2_StartIndex} # Group 2 start
Loop:
IntOp $R0 $R0 + 1
ReadINIStr "$R1" "$PLUGINSDIR\sections.ini" Sections $R0 # Get sec flags
SectionSetFlags $R0 $R1 # Re-set flags for this sec
StrCmp $R0 ${PROG2_EndIndex} 0 Loop
Pop $R1
Pop $R0
FunctionEnd
## Here we are selecting first sections to install
## by unselecting all the others!
Function SelectFilesA
# If user clicks Back now, we will know to reselect Group 2`s sections for
# Components page
StrCpy $IfBack 1
# We need to save the state of the Group 2 Sections
# for the next InstFiles page
Push $R0
Push $R1
StrCpy $R0 ${PROG2_StartIndex} # Group 2 start
# Don`t install prog 1?
Call IsPROG1Selected
Pop $R0
StrCmp $R0 1 +4
Pop $R1
Pop $R0
Abort
# Set current $INSTDIR to PROG1_InstDir define
StrCpy $INSTDIR "${PROG1_InstDir}"
Pop $R1
Pop $R0
FunctionEnd
## Here we need to unselect all Group 1 sections
## and then re-select those in Group 2 (that the user had selected on
## Components page)
Function SelectFilesB
Push $R0
;Push $R1
StrCpy $R0 ${PROG1_StartIndex} # Group 1 start
# Don't install prog 2?
Call IsPROG2Selected
Pop $R0
StrCmp $R0 1 +4
Pop $R1
Pop $R0
Abort
# Set current $INSTDIR to PROG2_InstDir define
StrCpy $INSTDIR "${PROG2_InstDir}"
;Pop $R1
Pop $R0
FunctionEnd
## Here we are deleting the temp INI file at the end of installation
Function DeleteSectionsINI
FlushINI "$PLUGINSDIR\Sections.ini"
Delete "$PLUGINSDIR\Sections.ini"
# FlexLM libs
;MessageBox MB_OK "DeleteSectionsINI #1 MyAppInstallDir is $MyAppInstallDir"
Delete $MyAppInstallDir\installs.exe
Delete $MyAppInstallDir\lmdown.exe
Delete $MyAppInstallDir\lmflex.exe
Delete $MyAppInstallDir\MyAppLicense.txt
Delete $MyAppInstallDir\MyCompany_LandingPage_114.bmp
# MyApp files
Delete $FlexLmInstallDir\config.dat
Delete $FlexLmInstallDir\MyApp.exe
Delete $FlexLmInstallDir\ReleaseNotes.txt
Delete $FlexLmInstallDir\MyCompany_LandingPage_114.bmp
Delete $FlexLmInstallDir\MyAppLicense.txt
Delete $FlexLmInstallDir\vcruntime140_1.dll
FunctionEnd
!else
# Uninstaller:
##############
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro DeclareLanguages
!verbose push 2
SilentInstall Silent
Section
WriteUninstaller "${GENRATINGUNINST}"
Quit
SectionEnd
!verbose pop
Section -Uninstall
# now delete installed files and registry keys for MyApp
ReadRegStr $0 HKCU "SOFTWARE\${COMPANY_NAME}" "InstallLocation"
DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}"
Delete $0\config.dat
Delete $0\MyApp.exe
Delete $0\ReleaseNotes.txt
Delete $0\MyCompany_LandingPage_114.bmp
Delete $0\MyAppLicense.txt
Delete "$SMPROGRAMS\MyApp.lnk"
DeleteRegKey HKCU "SOFTWARE\${PRODUCT_NAME}"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
DeleteRegKey /ifempty HKCU "Software\Modern UI Test"
# Final cleanup
RMDir $0
Delete "$InstDir\Uninst.exe"
RMDir "$InstDir"
SectionEnd
!endif
Here is a Github link to the source code that now builds: https://github.com/john1726/NsisInstal.git
Here is the full build log:
https://pastebin.com/rM2WjYm0
Does anyone have any suggestions? TIA.
The section is executed twice because you never deselect the section after "its" instfiles page. The code on the wiki does !insertmacro UnselectSection but you have removed this from your code. You have also removed the call to WriteINIStr!
There is no reason to have two instfiles pages, it just makes things terribly complicated.
If you use two directory pages and just one instfiles page you don't have to manipulate the sections at all:
!include "LogicLib.nsh"
!include "MUI2.nsh"
Var App1Dir
Var App2Dir
Function .onInit
StrCpy $App1Dir $ProgramFiles\App1
StrCpy $App2Dir $ProgramFiles\App2
FunctionEnd
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${__FILE__}"
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onFirstDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $App1Dir
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onLastDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $App2Dir
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLiSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLiSH} "Setup will install \
${FLEX_LM} in the following folder..."
Section App1 SID_APP1
StrCpy $InstDir $App1Dir
SetOutPath $InstDir
; File ...
MessageBox '' "Installing App1 to $InstDir"
SectionEnd
Section /o App2 SID_APP2
StrCpy $InstDir $App2Dir
SetOutPath $InstDir
; File ...
MessageBox '' "Installing App2 to $InstDir"
SectionEnd
Function onFirstDirPre
${IfNot} ${SectionIsSelected} ${SID_APP1}
Abort ; skip page
${EndIf}
${IfNot} ${SectionIsSelected} ${SID_APP2}
GetDlgItem $0 $hwndParent 1
SendMessage $0 ${WM_SETTEXT} "" "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd
Function onLastDirPre
${IfNot} ${SectionIsSelected} ${SID_APP2}
Abort ; skip page
${EndIf}
FunctionEnd
Function ComponentsLeave
StrCpy $0 0
StrCpy $1 ""
loop:
ClearErrors
SectionGetText $0 $2
IfErrors end
${If} ${SectionIsSelected} $0
${AndIf} $2 != ""
StrCpy $1 1
${EndIf}
IntOp $0 $0 + 1
Goto loop
end:
${If} $1 == ""
MessageBox mb_iconstop "Must select at least one!"
Abort ; stay on page
${EndIf}
FunctionEnd
Here is the final script that I ended up using which also contains an uninstaller, cleans up registry settings on uninstall, and added a splash bitmap, etc.
https://github.com/john1726/NsisInstal.git
Here is the actual code:
!include "LogicLib.nsh"
;Include Modern UI
!include "MUI2.nsh"
!include "Sections.nsh"
!define MAJOR_VERSION "1"
!define MINOR_VERSION "2"
!define PATCH_VERSION "3"
!define BUILD_VERSION "4"
!define APP_COPYRIGHT "MyApp © MyCompany 2021"
!define COMPANY_NAME "MyCompany"
!define FLEX_LM "FlexLM"
!define FLEX_DIR "FlexSQI"
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"
BrandingText "${COMPANY_NAME}"
OutFile ${SETUP_NAME}
Icon "favicon.ico"
UninstallIcon "favicon.ico"
!define MUI_ICON "favicon.ico"
!define MUI_UNICON "favicon.ico"
Name "${PRODUCT_NAME}"
InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
InstallDirRegKey HKLM "Software\$PRODUCT_NAME" ""
ShowInstDetails hide
ShowUnInstDetails hide
SetCompressor /SOLID lzma
SetCompressorDictSize 12
;Request application privileges for Windows
RequestExecutionLevel admin
!macro WriteSignedUninstaller Destination
!makensis '"/DGENRATINGUNINST=$%TEMP%\Uninst.exe" "${__FILE__}" "/XOutfile `$%TEMP%\tempinstaller.exe`"' = 0 ; Create fake installer
!system 'set __COMPAT_LAYER=RunAsInvoker&"$%TEMP%\tempinstaller.exe"' = 2 ; Run fake installer to generate the uninstaller
!system 'SIGNTOOL sign /f CodeSigningCertificate/MyCompany.pfx /p Test /tr http://timestamp.digicert.com /td SHA256 "$%TEMP%\Uninst.exe"' = 0 ; Change this line. As a demonstration, use !system 'echo Dummy >> "$%TEMP%\Uninst.exe"'
File "/oname=${Destination}" "$%TEMP%\Uninst.exe"
!macroend
!macro DeclareLanguages
# Define languages that the installer has
!insertmacro MUI_LANGUAGE "English"
!macroend
!ifndef GENRATINGUNINST
Var MyAppInstallDir
Var FlexLmInstallDir
## Create $PLUGINSDIR
Function .onInit
StrCpy $MyAppInstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
StrCpy $FlexLmInstallDir "C:\${FLEX_DIR}\"
InitPluginsDir
SetOutPath $TEMP
File /oname=spltmp.bmp "MyCompany_LandingPage_114.bmp"
splash::show 2000 $TEMP\spltmp
Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normally, and '-1' if some error occurred.
Delete $TEMP\spltmp.bmp
FunctionEnd
# Installer:
############
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "MyAppLicense.txt"
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS
## This is the title on the MyApp Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onFirstDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $MyAppInstallDir
!insertmacro MUI_PAGE_DIRECTORY
## This is the title on the FlexLM Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onLastDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $FlexLmInstallDir
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE DeleteSectionsINI
!insertmacro MUI_PAGE_FINISH
!insertmacro DeclareLanguages
;--------------------------------
LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLiSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLiSH} "Setup will install \
${FLEX_LM} in the following folder..."
Section App1 SID_APP1
StrCpy $InstDir $MyAppInstallDir
SetOutPath $InstDir
!insertmacro WriteSignedUninstaller "$InstDir\Uninst.exe"
File MyApp.exe
File ReleaseNotes.txt
File MyCompany_LandingPage_114.bmp
File MyAppLicense.txt
# create a shortcut named "new shortcut" in the start menu programs directory
CreateShortcut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" "$InstDir\${PRODUCT_NAME}.exe"
# Add application to registry
ClearErrors
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Contact' "https://www.mycompany.com/contact"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Company Name' "${COMPANY_NAME}"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'DisplayName' "${PRODUCT_NAME}"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'DisplayVersion' "${PRODUCT_VERSION}"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'AppID' "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'HelpLink' "http://www.myproduct.com/MyApp/HelpDocs/index.htm"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'URLInfoAbout' "https://www.mycompany.com/myapp"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'InstallLocation' "$MyAppInstallDir"
WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Publisher' "${COMPANY_NAME}"
# Add program to Add/Remove programs
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayIcon" "$PROGRAMFILES64\${PRODUCT_NAME}\${PRODUCT_NAME}.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"Publisher" "${COMPANY_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"UninstallString" "$\"$INSTDIR\Uninst.exe$\""
;MessageBox '' "Installing App1 to $InstDir"
SectionEnd
Section /o App2 SID_APP2
StrCpy $InstDir $FlexLmInstallDir
SetOutPath $InstDir
File installs.exe
File lmdown.exe
File lmflex.exe
; MessageBox '' "Installing App2 to $InstDir"
SectionEnd
Function onFirstDirPre
${IfNot} ${SectionIsSelected} ${SID_APP1}
Abort ; skip page
${EndIf}
${IfNot} ${SectionIsSelected} ${SID_APP2}
GetDlgItem $0 $hwndParent 1
SendMessage $0 ${WM_SETTEXT} "" "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd
Function onLastDirPre
${IfNot} ${SectionIsSelected} ${SID_APP2}
Abort ; skip page
${EndIf}
FunctionEnd
Function ComponentsLeave
StrCpy $0 0
StrCpy $1 ""
loop:
ClearErrors
SectionGetText $0 $2
IfErrors end
${If} ${SectionIsSelected} $0
${AndIf} $2 != ""
StrCpy $1 1
${EndIf}
IntOp $0 $0 + 1
Goto loop
end:
${If} $1 == ""
MessageBox mb_iconstop "You haven't selected any sections!"
Abort ; stay on page
${EndIf}
FunctionEnd
## Here we are deleting the temp INI file at the end of installation
Function DeleteSectionsINI
FlushINI "$INSTDIR\Sections.ini"
Delete "$INSTDIR\Sections.ini"
Delete $MyAppInstallDir\MyCompany_LandingPage_114.bmp
FunctionEnd
!else
# Uninstaller:
##############
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro DeclareLanguages
!verbose push 2
SilentInstall Silent
Section
WriteUninstaller "${GENRATINGUNINST}"
Quit
SectionEnd
!verbose pop
Section -Uninstall
# now delete installed files and registry keys for MyApp
ReadRegStr $0 HKCU "SOFTWARE\${COMPANY_NAME}" "InstallLocation"
;MessageBox MB_OK 'Uninstall InstallLocation = $0'
Delete $0\config.dat
Delete $0\MyApp.exe
Delete $0\ReleaseNotes.txt
Delete $0\MyCompany_LandingPage_114.bmp
Delete $0\MyAppLicense.txt
Delete "$SMPROGRAMS\MyApp.lnk"
DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}\${PRODUCT_NAME}"
DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
DeleteRegKey /ifempty HKCU "Software\Modern UI Test"
# Final cleanup
Delete "$InstDir\Uninst.exe"
RMDir $0
RMDir "$InstDir"
SectionEnd
!endif
I'm trying to add text or add an extra dialog at the end of an NSIS installer. So, to clarify, when the install has completed successfully I want to show some information.
I've seen various examples that touch on it but none seem to actually present a solution.
Does anyone have any info that can help?
You are already using the MUI so you can just customize the finish page text to fit your needs:
!include MUI2.nsh
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_TITLE "Custom title"
!define MUI_FINISHPAGE_TITLE_3LINES
!define MUI_FINISHPAGE_TEXT "Custom text blah blah blah$\r$\nblah blah blah$\r$\nblah blah blah$\r$\nblah blah blah$\r$\nblah blah blah$\r$\n"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
And if that is unacceptable for whatever reason, you can create a totally custom page:
!include MUI2.nsh
!insertmacro MUI_PAGE_INSTFILES
AutoCloseWindow True ; Automatically move on from the InstFiles page
Page Custom MyFinishPageCreate
!insertmacro MUI_LANGUAGE English
!include nsDialogs.nsh
Function MyFinishPageCreate
!ifdef MUI_SYSVERSION
!insertmacro MUI_HEADER_TEXT "Title" "Sub-title"
!endif
nsDialogs::Create 1018
Pop $0
${NSD_CreateLabel} 0 0 100% 12u "Blah blah blah"
Pop $0
${NSD_CreateLabel} 0 30u 100% -30u "More blah blah blah"
Pop $0
nsDialogs::Show
FunctionEnd
If you want to display text directly on the InstFiles page you have to create a label control manually:
!include LogicLib.nsh
!include nsDialogs.nsh
!include WinMessages.nsh
Page InstFiles "" InstFilesShow
Var MyText
Function InstFilesShow
; Cannot use CreateWindowEx in a Section, must do it in the show callback
FindWindow $1 "#32770" "" $HWNDPARENT # Finds the inner dialog
System::Call 'USER32::CreateWindowEx(i${__NSD_Label_EXSTYLE},t "${__NSD_Label_CLASS}",t "Text goes here",i${__NSD_Label_STYLE},i10,i100,i300,i200,p$1,p0,p0,p0)p.s'
Pop $MyText
ShowWindow $MyText 0
SendMessage $1 ${WM_GETFONT} 0 0 $2
SendMessage $MyText ${WM_SETFONT} $2 1
FunctionEnd
Section
${IfNot} ${Abort}
ShowWindow $MyText 1
${EndIf}
SectionEnd
I have an NSIS installer script with two SectionGroups. Each SectionGroup has two Sections, which are mutually exclusive.
I need to have the user able to uncheck the SectionGroup, which unchecks and disables ("grays-out") the Sections. Basically the user can choose to install one of the Sections, or none. On top of that, the second SectionGroup must be disabled if the first SectionGroup is unchecked.
I'm using this script as reference to control the mutually exclusive Sections: http://nsis.sourceforge.net/Mutually_Exclusive_Sections
Thanks in advance.
Your disable/gray requirement does not make sense. If you click the section group again to enable the "child sections", which of the two gets checked? And you would only be able to get out of the disabled state by clicking the group itself so I did not implement it.
In general, anything beyond simple radio button behavior gets complicated quickly. If you are using the 3.0 alpha version of NSIS then .onSelChange will actually tell you which item that changed which would make this less complicated...
Page Components "" SaveState
Page Instfiles
!include sections.nsh
!include logiclib.nsh
SectionGroup /e "Grp1" GRP_1
Section "A" SEC_A
SectionEnd
Section /o "B" SEC_B
SectionEnd
SectionGroupEnd
SectionGroup /e "Grp2" GRP_2
Section /o "C" SEC_C
SectionEnd
Section "D" SEC_D
SectionEnd
SectionGroupEnd
; Remove comments for a different behavior
Function SaveState
!macro SaveSel id var
SectionGetFlags ${id} ${var}
IntOp ${var} ${var} & ${SF_SELECTED}
!macroend
#SectionGetFlags ${GRP_1} $R0
!insertmacro SaveSel ${SEC_A} $R1
!insertmacro SaveSel ${SEC_B} $R2
#SectionGetFlags ${GRP_2} $R3
!insertmacro SaveSel ${SEC_C} $R4
!insertmacro SaveSel ${SEC_D} $R5
FunctionEnd
Function .onSelChange
!macro OneOfTwoItemsInAGroup gid gv i1 v1 i2 v2
#SectionGetFlags ${gid} $0
!insertmacro SaveSel ${i1} $1
!insertmacro SaveSel ${i2} $2
${If} $1 <> 0
${AndIf} $2 <> 0
StrCpy $1 ${i1}
${IfThen} ${v1} = 0 ${|} StrCpy $1 ${i2} ${|}
!insertmacro UnselectSection $1
/*${If} ${gv} = $0
!insertmacro UnselectSection ${gid}
${EndIf}*/
${EndIf}
!macroend
!insertmacro OneOfTwoItemsInAGroup ${GRP_1} $R0 ${SEC_A} $R1 ${SEC_B} $R2
!insertmacro OneOfTwoItemsInAGroup ${GRP_2} $R3 ${SEC_C} $R4 ${SEC_D} $R5
Call SaveState
FunctionEnd
is there any possibility to show some descriptive text on NSIS installer custom page, but only on mouse hover?
I have the prerequisites check at the beginning of the installer and when one (or more) of the tests fail, appropriate warning message is displayed. It is custom page displayed before whole installation. The problem is, that there are too many messages (in the worst case) and installer page small -- it isn't possible to show all of them without overlaying... So I would like to display only some title (briefly describing the problem) and more detailed information somewhere below in the dedicated area, but only when mouse moved over the brief text. Or, other solution is to create some scrollable area...
But I don't know how to do it in NSIS. I know .onMouseOverSection callback, but AFAIK it can be used only in section selection page.
Is it possible to do it in NSIS page?
Thanks in advance.
I don't think doing this on the instfiles page is a good idea. I would go for a custom page. If you decide to go with the custom page idea, you probably have 3 options:
Create a custom nsis plugin that shows a page in any way you want.
Create a custom page with nsDialogs and handle the mouse messages with the WndSubclass plugin.
Use two component pages and tweak one of them.
The following example uses the 3rd option since it uses only official nsis plugins.
OutFile "$%temp%\test.exe"
Name "Prereq desc"
RequestExecutionLevel user
!include MUI2.nsh
!define MUI_PAGE_HEADER_TEXT "Header blablah"
!define MUI_PAGE_HEADER_SUBTEXT "subheader blablah"
!define MUI_COMPONENTSPAGE_TEXT_TOP "blablah 1"
!define MUI_COMPONENTSPAGE_TEXT_INSTTYPE " "
!define MUI_COMPONENTSPAGE_TEXT_COMPLIST " "
!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE "blablah 4"
!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "blablah 5"
!define MUI_PAGE_CUSTOMFUNCTION_PRE prereqcreate
!define MUI_PAGE_CUSTOMFUNCTION_SHOW prereqshow
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_PRE componentscreate
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
Function .onInit
InitPluginsDir
StrCpy $0 0
loop:
ClearErrors
SectionGetText $0 $1
IfErrors done
WriteIniStr "$Pluginsdir\sec.ini" S $0 $1 ;Save section names...
IntOp $0 $0 + 1
Goto loop
done:
FunctionEnd
!macro ShowSections initial flip
StrCpy $0 0
StrCpy $2 ${initial}
loop:
ClearErrors
SectionGetText $0 $1
IfErrors done
ReadIniStr $1 "$Pluginsdir\sec.ini" S $0
IntCmpU 0 $2 "" +2 +2
StrCpy $1 ""
SectionSetText $0 $1
IntOp $0 $0 + 1
IntCmpU $0 ${flip} "" +2 +2
IntOp $2 $2 !
Goto loop
done:
!macroend
!macro CreatePreReq text name
Section /o "${text}" ${name}
SectionIn RO
SectionEnd
!macroend
!insertmacro CreatePreReq "Windows Installer v4.5" SEC_PRMSI
!insertmacro CreatePreReq ".NET v666" SEC_PRDOTNET
Section "Program files" SEC_PROG
;...
SectionEnd
Section "Desktop shortcut" SEC_DESKLNK
;...
SectionEnd
!define FIRSTREALSECTION ${SEC_PROG}
Function prereqcreate
!insertmacro ShowSections 1 ${FIRSTREALSECTION}
FunctionEnd
Function prereqshow
FindWindow $0 "#32770" "" $HWNDPARENT
GetDlgItem $1 $0 0x3FD
ShowWindow $1 0
GetDlgItem $1 $0 0x3FE
ShowWindow $1 0
GetDlgItem $1 $0 0x3FF
ShowWindow $1 0 ;hide space texts
GetDlgItem $1 $0 0x408
!define TVM_SETIMAGELIST 0x1109
SendMessage $1 ${TVM_SETIMAGELIST} 2 0 ;Remove images (leaking the imagelist in the process, oh well)
System::Call '*(&i24)i.r2'
System::Call 'user32::GetWindowRect(ir1,ir2)'
System::Call 'user32::MapWindowPoints(i0,ir0,ir2,i2)'
System::Call '*$2(i,i.r0,i.r3,i.r4)'
System::Free $2
IntOp $4 $4 - $0
System::Call 'user32::SetWindowPos(ir1,i0,i0,ir0,ir3,ir4,i0)'
FunctionEnd
Function componentscreate
!insertmacro ShowSections 0 ${FIRSTREALSECTION}
FunctionEnd
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_PRMSI} "You need MSI in a NSIS installer? ;)"
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_PRDOTNET} "You need moar bloat!"
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_PROG} "Required program files..."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKLNK} "Stupid desktop shortcut"
!insertmacro MUI_FUNCTION_DESCRIPTION_END