How do I make a section required for a sectiongroup in NSIS? - nsis

I want to make a section inside of a sectiongroup required for that section group but not required for the entire install if the group is unchecked. I've tried "SectionIn R0" but this makes that section required for the entire install and I only want it to be required if they select the group itself.
SectionGroup "group"
Section "required for section group"
SectionIn RO
SectionEnd
Section "optional"
SectionEnd
SectionGroupEnd

You can't do this with just properties, you need some actual code:
!include Sections.nsh
!include LogicLib.nsh
SectionGroup /e "group"
Section "required for section group" SEC_REQ
SectionIn RO
SectionEnd
Section "optional" SEC_OPT
SectionEnd
SectionGroupEnd
Function .onSelChange
${If} ${SectionIsSelected} ${SEC_OPT}
!define /math MYSECTIONFLAGS ${SF_SELECTED} | ${SF_RO}
!insertmacro SetSectionFlag ${SEC_REQ} ${MYSECTIONFLAGS}
!undef MYSECTIONFLAGS
${Else}
!insertmacro ClearSectionFlag ${SEC_REQ} ${SF_RO}
${EndIf}
FunctionEnd
Note that there is a "bug" when unchecking the section group itself, to workaround that, you need to keep some global state since nsis does not tell you which section generated the notification. The following code has better logic:
!include Sections.nsh
!include LogicLib.nsh
SectionGroup /e "group" SEC_GRP
Section "required for section group" SEC_REQ
SectionIn RO
SectionEnd
Section "optional" SEC_OPT
SectionEnd
Section "" PRIVSEC_TOGGLESTATE ;hidden section to keep track of state
SectionEnd
SectionGroupEnd
Function .onSelChange
!define /math SECFLAGS_SELRO ${SF_SELECTED} | ${SF_RO}
${IfNot} ${SectionIsSelected} ${PRIVSEC_TOGGLESTATE}
${AndIf} ${SectionIsReadOnly} ${SEC_REQ}
!insertmacro ClearSectionFlag ${SEC_REQ} ${SECFLAGS_SELRO}
${EndIf}
${If} ${SectionIsSelected} ${SEC_OPT}
!insertmacro SetSectionFlag ${SEC_REQ} ${SECFLAGS_SELRO}
${Else}
!insertmacro ClearSectionFlag ${SEC_REQ} ${SF_RO}
${EndIf}
${If} ${SectionIsSelected} ${SEC_REQ}
!insertmacro SelectSection ${PRIVSEC_TOGGLESTATE}
${Else}
!insertmacro UnselectSection ${PRIVSEC_TOGGLESTATE}
${EndIf}
!undef SECFLAGS_SELRO
FunctionEnd

You can also set the sections as mandatory sections by using the SectionSetFlags command. You simply need to add it to the .onInit function as follows:
SectionGroup "group" Sec01
Section "required for section group"
SectionIn RO
SectionEnd
Section "optional" Sec02
SectionEnd
SectionGroupEnd
Function .onInit
SectionSetFlags ${Sec01} 17
FunctionEnd
This will gray "group" out, but it will be selected and installed as expected.

You can also setup a custom function which is being called when user clicks "Next" but no option is selected. In this function, you can check if any of Sections is selected or, as I did, check the variable which is set to "nothingSelected" on init, then modified when any section is created. If you put "Abort" in the custom function, the installer will stay on the same page. Here is a snippet:
page license
page directory
page components "" "" testSelection
page instfiles
function .onInit
StrCpy $somethingSelected "nothingSelected"
functionEnd
function testSelection
${If} $somethingSelected == "nothingSelected"
MessageBox MB_OK "Please select any option"
Abort
${EndIf}
functionEnd
function .onSelChange
#selecting mutually exclusive sections (removed for clarity)
StrCpy $somethingSelected $1
functionEnd

Related

How to create shortcut for desktop and startmenu after installation in NSIS?

I am new to NSIS. I am trying to add this below style of the page in post-installation (i.e. before the finish page). Could anyone suggest, whether we can do a single custom page and add the necessary checkbox, radio button, and program groups ? or any other suggestions.
Below is my page sequence:
!insertmacro MUI_PAGE_DIRECTORY
;Custom page for selecting service name to restart.
Page custom nsDialogsSelectService ngDialogSelectServicePageLeave
; variable and text for the app data dir
!define MUI_DIRECTORYPAGE_VARIABLE $appDataDir
!define MUI_PAGE_HEADER_TEXT "Choose Data Directory"
!define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install application data for ${PRODUCT_FULL} ${PVERSION}."
!define MUI_DIRECTORYPAGE_TEXT_TOP "Setup will install data directory need todo. To install in a different folder, click Browse and select another folder. Click Next to Continue."
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Destination Folder"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_TITLE_3LINES
Page custom nsDialogShortcut ngDialogShortcutPageLeave ;Page contain checkbox , based on the selection of checkbox I am showing Startmenu and then finish page.
!insertmacro MUI_PAGE_STARTMENU 0 $SMDir
!insertmacro MUI_PAGE_FINISH
Giving the user the choice of user/machine shortcuts is in conflict with how UAC works. When a non-admin user elevates with an administrator account the installer will end up running with the "wrong" profile.
The Windows guidelines say that only application suites (with individual major applications, like MS Office) should create Start menu folders. Regular applications should create their (single) shortcut directly in $SMPrograms. You should not create shortcuts to the uninstaller nor help-files. You should also refrain from creating a desktop shortcut.
This means you can simply use the components page to provide the shortcut option(s):
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Section "Program files"
SectionIn RO
SetOutPath $InstDir
File "MyApp.exe"
SectionEnd
Section "Start menu shortcut"
CreateShortcut "$SMPrograms\$(^Name).lnk" "$InstDir\MyApp.exe"
SectionEnd
Section /o "Desktop shortcut"
CreateShortcut "$Desktop\$(^Name).lnk" "$InstDir\MyApp.exe"
SectionEnd
or as a checkbox on the Finish page:
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_SHOWREADME ""
!define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Start menu shortcut"
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateShortcuts
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Function CreateShortcuts
CreateShortcut "$SMPrograms\$(^Name).lnk" "$InstDir\MyApp.exe"
FunctionEnd
If you actually have a suite of applications then you can use the Start menu page to prompt for a folder name:
Var SMFolder
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE STARTMENU Suite $SMFolder
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Section
!insertmacro MUI_STARTMENU_WRITE_BEGIN Suite
CreateDirectory "$SMPrograms\$SMFolder"
CreateShortcut "$SMPrograms\$SMFolder\App1.lnk" "$InstDir\MyApp1.exe"
CreateShortcut "$SMPrograms\$SMFolder\App2.lnk" "$InstDir\MyApp2.exe"
; TODO: Write $SMFolder to the registry or a .ini so your uninstaller can delete the folder
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
In the unlikely event that you have a suite of applications and you also want to create desktop shortcuts then yes, you need to use a custom page:
Var SMDir
Var SMCheck
Var DeskCheck
Var SMList
Var SMDirEdit
!include LogicLib.nsh
!include nsDialogs.nsh
!include MUI2.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
Page Custom MyShortcutsPageCreate MyShortcutsPageLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Function .onInit
StrCpy $SMDir "$(^Name)" ; Default
StrCpy $SMCheck ${BST_CHECKED}
FunctionEnd
Function MyShortcutsPageCreate
!insertmacro MUI_HEADER_TEXT "Shortcuts" "Shortcuts blah blah blah"
nsDialogs::Create 1018
Pop $0
${IfThen} $0 == error ${|} Abort ${|}
${NSD_CreateCheckbox} 0 0u 50% 12u "Create Start menu shortcuts"
Pop $R8
SendMessage $R8 ${BM_SETCHECK} $SMCheck ""
${NSD_CreateCheckbox} 0 14u 50% 12u "Create desktop shortcuts"
Pop $R9
SendMessage $R9 ${BM_SETCHECK} $DeskCheck ""
${NSD_CreateSortedListBox} 0 28u 100% -43u ""
Pop $SMList
${NSD_CreateText} 0 -13u 100% 12u "$SMDir"
Pop $SMDirEdit
${NSD_LB_AddString} $SMList "(Default)"
${NSD_LB_SetItemData} $SMList 0 1 ; Mark as special
SetShellVarContext Current
Call FillSMList
SetShellVarContext All
Call FillSMList
SetShellVarContext ? ; TODO: Restore to what you actually are installing as
${NSD_OnChange} $SMList OnSMListChanged
${NSD_OnClick} $R8 OnSMCheckChanged
Push $R8
Call OnSMCheckChanged
nsDialogs::Show
FunctionEnd
Function FillSMList
FindFirst $0 $1 "$SMPrograms\*"
loop:
StrCmp $1 "" done
${If} ${FileExists} "$SMPrograms\$1\*.*"
${AndIf} $1 != "."
${AndIf} $1 != ".."
${NSD_LB_FindStringExact} $SMList "$1" $2
${If} $2 < 0
${NSD_LB_AddString} $SMList $1
${EndIf}
${EndIf}
FindNext $0 $1
Goto loop
done:
FindClose $0
FunctionEnd
Function OnSMCheckChanged
Pop $0
${NSD_GetChecked} $0 $0
EnableWindow $SMList $0
EnableWindow $SMDirEdit $0
FunctionEnd
Function OnSMListChanged
Pop $0
${NSD_LB_GetSelection} $SMList $0
${NSD_SetText} $SMDirEdit "$0\$(^Name)"
${NSD_LB_GetSelectionIndex} $SMList $0
${NSD_LB_GetItemData} $SMList $0 $0
${If} $0 <> 0
${NSD_SetText} $SMDirEdit "$(^Name)"
${EndIf}
FunctionEnd
Function MyShortcutsPageLeave
${NSD_GetChecked} $R8 $SMCheck
${NSD_GetChecked} $R9 $DeskCheck
${NSD_GetText} $SMDirEdit $SMDir
FunctionEnd
Section
${If} $SMCheck <> 0
CreateDirectory "$SMPrograms\$SMDir"
CreateShortcut "$SMPrograms\$SMDir\App1.lnk" "$InstDir\App1.exe"
CreateShortcut "$SMPrograms\$SMDir\App2.lnk" "$InstDir\App2.exe"
${EndIf}
${If} $DeskCheck <> 0
CreateShortcut "$Desktop\App1.lnk" "$InstDir\App1.exe"
CreateShortcut "$Desktop\App2.lnk" "$InstDir\App2.exe"
${EndIf}
SectionEnd

NSIS Selections Page

I was originally going to ask how to do several of the features I how have working in the set file. so I have 2 questions now. Patting myself on the back since I figured out everything else:)
Ok so here is what I would like:
Is it possible to have the list taller so no scrolling? also
Can we have the title be just that and no checkbox? (They are radio-buttons and the title is the grouping of them)
How could I go about creating the same thing just in a custom page so I have control over the elements? (including the mouse move over feature of components page)
Thanks for looking and hope you can help me code it out.
Code: (And yes I know the !included's are not all needed in the test buy my app does so I just left it) Also the verification and a few other settings are not finished, I was just getting some examples to work.)
!include WinVer.nsh
!include LogicLib.nsh
!include x64.nsh
!include FileFunc.nsh
!include MUI.nsh
!include WinMessages.nsh
!include InstallOptions.nsh
!include Sections.nsh
!define MUI_COMPONENTSPAGE_TEXT_TOP "Please select the options that best match your setup and preferances."
!define MUI_COMPONENTSPAGE_TEXT_COMPLIST " "
!define MUI_PAGE_HEADER_TEXT "Setup Options"
!define MUI_PAGE_HEADER_SUBTEXT " "
!define MUI_COMPONENTSPAGE_smallDESC
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
SectionGroup /e "!Sets" SetsTitle #Section Should be Radio Buttons
Section "Set 1" Set1
SectionEnd
Section /o "Set 2" Set2
SectionEnd
Section /o "Skip" SetSkip
SectionEnd
SectionGroupEnd
SubSection /e "!Setup" SetupTitle #Section Should be Radio Buttons
Section "Setup 1" setup1
SectionEnd
Section /o "Setup 2" setup2
SectionEnd
Section /o "None" setupNone
SectionEnd
SubSectionEnd
SubSection /e "!AutoLoad" ALTitle #Section Should be Radio Buttons
Section "Yes" ALYes
SectionEnd
Section /o "No" ALNo
SectionEnd
SubSectionEnd
SubSection /e "!Disable Feature" DFTitle #Section Should be Check Boxes
Section "Feature 1" DAF1
SectionEnd
Section "Feature 2" DAF2
SectionEnd
SubSectionEnd
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SetsTitle} "Sets Description"
!insertmacro MUI_DESCRIPTION_TEXT ${Set1} "Set1 Description"
!insertmacro MUI_DESCRIPTION_TEXT ${Set2} "Set2 Description"
!insertmacro MUI_DESCRIPTION_TEXT ${SetSkip} "SetNone Description"
!insertmacro MUI_FUNCTION_DESCRIPTION_END
Section -InstallSelectedOptions
${If} ${SectionIsSelected} ${set1}
MessageBox MB_OK|MB_USERICON|MB_TOPMOST "set1"
${endif}
${If} ${SectionIsSelected} ${set2}
MessageBox MB_OK|MB_USERICON|MB_TOPMOST "set2"
${endif}
${If} ${SectionIsSelected} ${setskip}
MessageBox MB_OK|MB_USERICON|MB_TOPMOST "setnone"
${endif}
${If} ${Setup1} == true
${endif}
SectionEnd
Function .onInit
StrCpy $1 ${set1} ; Group 1 - Option 1 is selected by default
StrCpy $2 ${setup1} ; Group 2 - Option 1 is selected by default
FunctionEnd
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${set1}
!insertmacro RadioButton ${set2}
!insertmacro RadioButton ${setskip}
!insertmacro EndRadioButtons
!insertmacro StartRadioButtons $2
!insertmacro RadioButton ${setup1}
!insertmacro RadioButton ${setup2}
!insertmacro RadioButton ${setupNone}
!insertmacro EndRadioButtons
FunctionEnd
You cannot combine radio buttons and checkmarks on the built-in components page but you can use your own custom radio button .BMP file with !define MUI_COMPONENTSPAGE_CHECKBITMAP "myradio.bmp".
You can customize the MUI components page a little bit by defining MUI_COMPONENTSPAGE_SMALLDESC or MUI_COMPONENTSPAGE_NODESC but if you need more than that you have to copy and modify "...\NSIS\Contrib\UIs\modern.exe" with Resource Hacker and apply this custom UI with MUI_UI.
Replicating the components page as a custom page might be possible but it is a lot of work. nsDialogs does not have much support for the TreeView control so you are pretty much on your own if you go down this route.

Skipping pages: Button should say "Install" instead of "Next"

I have an installer using the Modern UI 2 (MUI 2) that installs up to three components into different locations.
I use a MUI_PAGE_COMPONENTS page and multiple MUI_PAGE_DIRECTORY pages which are skipped automatically if the corresponding section is not selected (like described here).
So far so good.
However, if the last of the three components is not chosen to be installed, the button on the previous (not-skipped) directory page should say Install instead of Next, because next the last directory page will be skipped and the installation will be executed.
Since we already know which page will be skipped after we leave the components page, I wonder if there is a way to make it work?
Minimal example:
!include MUI2.nsh
InstallDir $EXEDIR
OutFile "skip.exe"
RequestExecutionLevel user
ShowInstDetails show
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_PRE directoryPreA
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_PRE directoryPreB
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
Section "A" SEC_A
DetailPrint "Installing A..."
SectionEnd
Section /o "B" SEC_B
DetailPrint "Installing B..."
SectionEnd
Function directoryPreA
# Skips the directory page for A if not chosen for installation.
${Unless} ${SectionIsSelected} ${SEC_A}
Abort
${EndUnless}
FunctionEnd
Function directoryPreB
# Skips the directory page for B if not chosen for installation.
${Unless} ${SectionIsSelected} ${SEC_B}
Abort
${EndUnless}
FunctionEnd
!include MUI2.nsh
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_DIRECTORYPAGE_TEXT_TOP "Dir:A"
!define MUI_PAGE_CUSTOMFUNCTION_PRE directoryPreA
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_DIRECTORYPAGE_TEXT_TOP "Dir:B"
!define MUI_PAGE_CUSTOMFUNCTION_PRE directoryPreB
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
Section "A" SEC_A
DetailPrint "Installing A..."
SectionEnd
Section /o "B" SEC_B
DetailPrint "Installing B..."
SectionEnd
Function .onSelChange
GetDlgItem $0 $HWNDPARENT 1
${If} ${SectionIsSelected} ${SEC_A}
${OrIf} ${SectionIsSelected} ${SEC_B}
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^NextBtn)"
${Else}
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd
Function directoryPreA
# Skips the directory page for A if not chosen for installation.
${IfNot} ${SectionIsSelected} ${SEC_A}
Abort
${ElseIfNot} ${SectionIsSelected} ${SEC_B}
GetDlgItem $0 $HWNDPARENT 1
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd
Function directoryPreB
# Skips the directory page for B if not chosen for installation.
${Unless} ${SectionIsSelected} ${SEC_B}
Abort
${EndUnless}
FunctionEnd

NSIS nsDialog has disabled back/next/cancel buttons?

I'm following the NSIS nsDialog tutorial with a goal to gather some user input I will use to write into a config file later. The NSISEclipse plugin has generated an MUI2 template that has gotten me started and successfully installs the files.
I have used the nsDialog tutorial to generate a dialog that does get emitted exactly where I want it to, but for some reason the "Back/Next/Cancel" buttons are all grey. I don't see where in the nsDialog documentation it says to enable/disable those buttons.
Here's my code:
Var Dialog
Var Label
Var MyTextBox
Section configLocationDialog
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
Pop $Label
${NSD_CreateText} 10% 20u 80% 12u "Hello World"
Pop $MyTextbox
nsDialogs::Show
SectionEnd
And, the dialog once displayed:
What do I need to change to tell NSIS to allow back/next/cancel?
EDIT More code was asked for. Here's the whole thing as it exists now.
# Auto-generated by EclipseNSIS Script Wizard
# Dec 19, 2013 3:48:34 PM
Name SecureKeypad
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION 1.0.0
!define COMPANY **COMPANY**
!define URL http://www.**COMPANY**.com
# MultiUser Symbol Definitions
!define MULTIUSER_EXECUTIONLEVEL Standard
!define MULTIUSER_INSTALLMODE_COMMANDLINE
!define MULTIUSER_INSTALLMODE_INSTDIR $PROGRAMFILES\SecureKeypad
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${REGKEY}"
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUE "Path"
# MUI Symbol Definitions
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
!define MUI_STARTMENUPAGE_DEFAULTFOLDER SecureKeypad
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall-colorful.ico"
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
# Included files
#!include MultiUser.nsh
!include LogicLib.nsh
!include nsDialogs.nsh
!include AdvReplaceInFile.nsh
!include Sections.nsh
!include MUI2.nsh
# Variables
Var StartMenuGroup
# Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
# Installer languages
!insertmacro MUI_LANGUAGE English
# Installer attributes
OutFile setup.exe
CRCCheck on
InstallDir $PROGRAMFILES\${COMPANY}\SecureKeypad
XPStyle on
ShowInstDetails show
VIProductVersion 1.0.0.0
VIAddVersionKey ProductName SecureKeypad
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
VIAddVersionKey CompanyWebsite "${URL}"
VIAddVersionKey FileVersion "${VERSION}"
VIAddVersionKey FileDescription ""
VIAddVersionKey LegalCopyright ""
InstallDirRegKey HKLM "${REGKEY}" Path
ShowUninstDetails show
# Input dialogs
Var Dialog
Var Label
Var MyTextbox
#Page custom configLocationDialog configLocationDialogLeave
#Page custom doConfiguration
Section configLocationDialog
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
GetFunctionAddress $0 "configLocationDialogLeave"
nsDialogs::OnBack $Dialog $0
#nsDialogs::OnNext $Dialog
${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
Pop $Label
${NSD_CreateText} 10% 20u 80% 12u "Hello World"
Pop $MyTextbox
nsDialogs::Show
SectionEnd
Function configLocationDialogLeave
${NSD_GetText} $MyTextbox $0
MessageBox mb_ok $0
FunctionEnd
# Installer sections
Section -Main SEC0000
SetOutPath $INSTDIR
SetOverwrite on
File installable-content\CYBSSecurity.dll
File installable-content\SecureKeypad.exe
File installable-content\SecureKeypad.exe.config
File installable-content\SecureKeypad.config
File installable-content\SecureKeypad.frmSecureKeypad.resources
WriteRegStr HKLM "${REGKEY}\Components" Main 1
!insertmacro AdvReplaceInFile $INSTDIR\SecureKeypad.exe.config "##configFile##" $INSTDIR
SectionEnd
Section -post SEC0001
WriteRegStr HKLM "${REGKEY}" Path $INSTDIR
SetOutPath $INSTDIR
WriteUninstaller $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
SetOutPath $SMPROGRAMS\$StartMenuGroup
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
SectionEnd
# Macro for selecting uninstaller sections
!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
Push $R0
ReadRegStr $R0 HKLM "${REGKEY}\Components" "${SECTION_NAME}"
StrCmp $R0 1 0 next${UNSECTION_ID}
!insertmacro SelectSection "${UNSECTION_ID}"
GoTo done${UNSECTION_ID}
next${UNSECTION_ID}:
!insertmacro UnselectSection "${UNSECTION_ID}"
done${UNSECTION_ID}:
Pop $R0
!macroend
# Uninstaller sections
Section /o -un.Main UNSEC0000
Delete /REBOOTOK $INSTDIR\SecureKeypad.frmSecureKeypad.resources
Delete /REBOOTOK $INSTDIR\SecureKeypad.exe.config
Delete /REBOOTOK $INSTDIR\SecureKeypad.exe
Delete /REBOOTOK $INSTDIR\<sensored>.dll
DeleteRegValue HKLM "${REGKEY}\Components" Main
SectionEnd
Section -un.post UNSEC0001
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk"
Delete /REBOOTOK $INSTDIR\uninstall.exe
DeleteRegValue HKLM "${REGKEY}" StartMenuGroup
DeleteRegValue HKLM "${REGKEY}" Path
DeleteRegKey /IfEmpty HKLM "${REGKEY}\Components"
DeleteRegKey /IfEmpty HKLM "${REGKEY}"
RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
RmDir /REBOOTOK $INSTDIR
SectionEnd
# Installer functions
Function .onInit
InitPluginsDir
FunctionEnd
# Uninstaller functions
Function un.onInit
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
!insertmacro SELECT_UNSECTION Main ${UNSEC0000}
FunctionEnd
Calling nsDialogs::Create/Show in a section is never valid, they can only be called in the create callback function of a custom page.
Some buttons will be disabled after the instfiles page (Already installed, cannot cancel or go back) but this is done by NSIS itself, not nsDialogs...
If you put your call to nsDialogs:Create in a section it will be run when the installer is installing files and such. In that state you won't be able to keep navigating through the pages in the installer and you are stuck.
Your notice about your custom page running at the end of the installer is really what you should be trying to fix, not dismissing it as the wrong way (it's the only way). NSIS-scripts are quite simple in many ways. For example, pages are loaded in the order that they are declared. So when you declare that you want MUI_PAGE_WELCOME, MUI_PAGE_DIRECTORY and the others you are also setting the order of them.
# Installer pages
!insertmacro MUI_PAGE_WELCOME # First page
!insertmacro MUI_PAGE_DIRECTORY # Second page
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup # Third page
!insertmacro MUI_PAGE_INSTFILES # Etc
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
So if you then try to keep all your code together and add your custom page alongside the functions that handle it, it will undoubtedly be the last page in that order.
# Installer pages
!insertmacro MUI_PAGE_WELCOME # First page
!insertmacro MUI_PAGE_DIRECTORY # Second page
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup # Third page
...
# Input dialogs
Var Dialog
Var Label
Var MyTextbox
Page custom configLocationDialog configLocationDialogLeave # Last page
Section configLocationDialog
nsDialogs::Create 1018
Pop $Dialog
So to illustrate this I took your code and brewed it down to basically the page you wanted.
# Included files
!include LogicLib.nsh
!include nsDialogs.nsh
!include Sections.nsh
!include MUI2.nsh
# Installer pages
!insertmacro MUI_PAGE_WELCOME # First page
Page custom configLocationDialog configLocationDialogLeave # Second page!
!insertmacro MUI_PAGE_FINISH # Last page
# Installer languages
!insertmacro MUI_LANGUAGE English
# Input dialogs
Var Dialog
Var Label
Var MyTextbox
Function configLocationDialog
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
GetFunctionAddress $0 "configLocationDialogLeave"
nsDialogs::OnBack $Dialog $0
${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
Pop $Label
${NSD_CreateText} 10% 20u 80% 12u "Hello World"
Pop $MyTextbox
nsDialogs::Show
FunctionEnd
Function configLocationDialogLeave
${NSD_GetText} $MyTextbox $0
MessageBox mb_ok $0
FunctionEnd
Section -Main SEC0000
SectionEnd
The NSISEclipse plugin generates a lot of code, including a set of macros that execute the various pages that are displayed:
# Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
The trick is to inject the page call at the right step.
# Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
Page custom configLocationDialog configLocationDialogLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

NSIS unattended options

I want to build a NSIS-script, which has three section
section Main
section Minor
section Shared
Shared is invisible and would be installed, if Main or Minor is checked. If I start the installer, every section (Main, Minor) is checked.
Now it should be able to define the section (in silent install). What have I to change, to only install Main or Minor or Both?
Name "Test"
Outfile "Test.exe"
;RequestExecutionLevel ?
!include "Sections.nsh"
!include "LogicLib.nsh"
!include "FileFunc.nsh" ;For GetOptions
Page Components "" "" EnforceSectionDependencies
Page InstFiles
Section /o "Main" SID_MAIN
DetailPrint Main
SectionEnd
Section /o "Minor" SID_MINOR
DetailPrint Minor
SectionEnd
Section "" SID_SHARED
DetailPrint Shared
SectionEnd
!macro CheckSectionSwitch sw sid
${GetOptions} $0 '${sw}' $9
${IfNot} ${Errors}
StrCpy $1 1
!insertmacro SelectSection ${sid}
${EndIf}
!macroend
Function .onInit
${GetParameters} $0
StrCpy $1 0 ;Any section swithes?
ClearErrors
!insertmacro CheckSectionSwitch '/Main' ${SID_MAIN}
!insertmacro CheckSectionSwitch '/Minor' ${SID_MINOR}
${If} $1 = 0
;Set defaults
!insertmacro SelectSection ${SID_MAIN}
!insertmacro SelectSection ${SID_MINOR}
${EndIf}
call EnforceSectionDependencies
FunctionEnd
Function EnforceSectionDependencies
!insertmacro UnselectSection ${SID_SHARED}
${If} ${SectionIsSelected} ${SID_MAIN}
${OrIf} ${SectionIsSelected} ${SID_MINOR}
!insertmacro SelectSection ${SID_SHARED}
${EndIf}
FunctionEnd
You should look at the Section management part of the documentation, notably the SectionSetFlags to change the sections selections.
Also, maybe that the How to control Section selections, while using SubSections & InstTypes example will be useful.

Resources