Search code examples
nsis

NSIS - Validating radio button selection


I have a really simple NSIS script that allows the user to select which component they would like to install, but I need a way of saying "Please select a component" if they haven't selected anything.

Here's the script:

# Based on the one-section example
# http://nsis.sourceforge.net/Examples/one-section.nsi

!include "sections.nsh"

Name "Humira & You"
OutFile "Humira & You - September 2012.exe"
RequestExecutionLevel user

Page components
Page instfiles

Section /o "Rheumatoid Arthritis" P1
    File "/oname=$pluginsdir\Setup.msi" "setupfiles\Humira and you - Rheumatoid Arthritis.msi"
SectionEnd

Section /o "Psoriatic Arthritis" P2
    File "/oname=$pluginsdir\Setup.msi" "setupfiles\Humira and you - Psoriatic Arthritis.msi"
SectionEnd

Section /o "Ankylosing Spondylitis" P3
    File "/oname=$pluginsdir\Setup.msi" "setupfiles\Humira and you - Ankylosing Spondylitis.msi"
SectionEnd

Section /o "Axial Spondyloarthritis" P4
    File "/oname=$pluginsdir\Setup.msi" "setupfiles\Humira and you - Axial Spondyloarthritis.msi"
SectionEnd

Section ; Hidden section that runs the show
    DetailPrint "Installing selected application..."
    SetDetailsPrint none
    ExecWait '"msiexec" /i "$pluginsdir\Setup.msi"'
    SetDetailsPrint lastused
SectionEnd

Function .onInit
    Initpluginsdir ; Make sure $pluginsdir exists
    StrCpy $1 ${P2} ;The default
FunctionEnd

Function .onSelChange
!insertmacro StartRadioButtons $1
    !insertmacro RadioButton ${P1}
    !insertmacro RadioButton ${P2}
    !insertmacro RadioButton ${P3}
    !insertmacro RadioButton ${P4}
!insertmacro EndRadioButtons
FunctionEnd

I had a look around and came across this example, http://nsis.sourceforge.net/Useful_InstallOptions_and_MUI_macros#Macro:_CHECKBOXCHECKER, but it seems overly complex for what I want. Is there no way to say in NSIS:

if ($1.selectedIndex > -1) {
   // continue
} else {
   MessageBox.Show("Please select");
}

Thanks, Greg.


Solution

  • You can use a callback function when leaving the components page to check if one is selected.

    Here is a piece of code that I use in a setup. I use a little macro to summarize in a variable the selected components. If there is none, the variable is null. I use the PageEx block to associate callback functions to the component page (as the leave callback is the third one, I use a dummy function for the first two others)

    Replace

    Page components
    

    by

    PageEx components
        PageCallbacks DummyFunc DummyFunc componentsLeave
    PageExEnd
    

    keep your .onSelChange call back to handle exclusive selection, then add this to the end of your script :

    !define SECTIONCOUNT 3 ; total -1
    ;SaveSections adds one bit to the given variable for each selected component
    !macro SaveSections VAR
        StrCpy ${VAR} 0
        ${ForEach} $R0 ${SECTIONCOUNT} 0 - 1
            IntOp ${VAR} ${VAR} << 1
            ${If} ${SectionIsSelected} $R0
                ;${DEBUG} "Section $R0 checked"
                IntOp ${VAR} ${VAR} + 1
            ${EndIf}
        ${Next}
    !macroend
    
    Function DummyFunc
    FunctionEnd
    
    Function componentsLeave
        !insertmacro SaveSections $2
        ${if} $2 = 0
            MessageBox MB_OK|MB_ICONEXCLAMATION "Select something !" /sd IDOK
            Abort
        ${endif}
    FunctionEnd