I've searched through the forums and i've found part of my answer however i still can't seem to get the Next button to be active.
If i had this ini:
[Settings]
NumFields=3
[Field 1]
Type=RadioButton
Text=Option1
Left=42
Right=-1
Top=11
Bottom=20
[Field 2]
Type=RadioButton
Text=Option2
Left=42
Right=-1
Top=33
Bottom=48
[Field 3]
Type=RadioButton
Text=Option3
Left=42
Right=-1
Top=59
Bottom=73
and my nsi was something like this:
Page custom ChooseSetup
.
.
.
Function ChooseSetup
;******Disable the NEXT button, until a radio button has been clicked
GetDlgItem $1 $HWNDPARENT 1
EnableWindow $1 0
!insertmacro MUI_HEADER_TEXT "Choose a Setup" "Choose which Setup you want to install."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "$PLUGINSDIR\SetupOptions.ini"
FunctionEnd
How do I enable the "Next" button once a radio button has been clicked? I've looked at testnotify.nsi, but if i did the "Page custom ChooseSetup ChooseSetup_Leaving" the ChooseSetup_Leaving only works if I left the page and thus have already clicked Next.
I thought if i did the follwing it would work:
ReadIniStr $0 '$PLUGINSDIR\SetupOptions.ini' "Field 1" "State"
ReadIniStr $1 '$PLUGINSDIR\SetupOptions.ini' "Field 2" "State"
ReadIniStr $2 '$PLUGINSDIR\SetupOptions.ini' "Field 3" "State"
${If} $1 == 1
${OrIf) $2 == 1
$(OrIf) $3 == 1
GetDlgItem $1 $HWNDPARENT 1
EnableWindow $1 0
${EndIf}
where am i going wrong? Thanks.
Radio buttons and Next Button
21 posts
You must use the NOTIFY flag on the radio buttons for the leave function to be called when they're clicked.
great thanks! but what if i didn't want to leave the page and i wanted them to have to click NEXT in order to get to the next page?
NOTIFY ensures the leave function is called. In there you need to check which radio button was selected (read from Settings>State to get the field # of the radio button). Call Abort to go back to the page, or rather to prevent the user leaving the page.
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 0
That will disable the next button.
Stu
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 0
That will disable the next button.
Stu
ok i tried what you suggested. However the is still something wrong. my leave function looks like this:
Function ChooseSetup_Leave
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 1
IntCmp $0 0 validate
Abort
validate:
MessageBox MB_ICONEXCLAMATION|MB_OK "Just a Message"
Abort
FunctionEnd
what happens is that when I select one of my radio buttons, it will automatically generate the MessageBox. The MessageBox should only appear when I hit Next. From what I've read 0 is the Next Button.
I'm using V2.1, if it helps.
Function ChooseSetup_Leave
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 1
IntCmp $0 0 validate
Abort
validate:
MessageBox MB_ICONEXCLAMATION|MB_OK "Just a Message"
Abort
FunctionEnd
what happens is that when I select one of my radio buttons, it will automatically generate the MessageBox. The MessageBox should only appear when I hit Next. From what I've read 0 is the Next Button.
I'm using V2.1, if it helps.
one more thing, because of the Abort in
.
.
.
validate:
MessageBox MB_ICONEXCLAMATION|MB_OK "You must select at least one install option!"
Abort
I also can't leave the page when I press Next.
.
.
.
validate:
MessageBox MB_ICONEXCLAMATION|MB_OK "You must select at least one install option!"
Abort
I also can't leave the page when I press Next.
StuPage custom ChooseSetup ChooseSetupLeave
Function ChooseSetup
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 0
!insertmacro MUI_HEADER_TEXT "Choose a Setup" "Choose which Setup you want to install."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY SetupOptions.ini
FunctionEnd
Function ChooseSetupLeave
!insertmacro MUI_INSTALLOPTIONS_READ $R0 SetupOptions.ini Settings State
${If} $R0 == 1
${OrIf} $R0 == 2
${OrIf} $R0 == 3
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 1
Abort
${EndIf}
FunctionEnd
awesome! thanks a bunch!
trying to light up Next after one of the option selected first; but not before,
can someone please help me out here; why wont this work...
TIA
Chris,
can someone please help me out here; why wont this work...
TIA
Chris,
SetCompressor lzma
; MUI 1.67 compatible ------
!include "MUI.nsh"
!include nsDialogs.nsh
; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
XPStyle on
Var Dialog
Var GroupBox1
Var RadioButton1
Var RadioButton2
Var RadioButton3
Var RadioButton4
Var RadioButton1_State
Var RadioButton2_State
Var RadioButton3_State
Var RadioButton4_State
Page custom nsDialogsPage nsDialogsPageLeave
Function nsDialogsPage
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 0
nsDialogs::Create 1018
Pop $Dialog
${NSD_CreateGroupBox} 5u 0u 96.5% 55u "Choose Install option below"
Pop $GroupBox1
${NSD_CreateRadioButton} 10u 12u 60% 10u "&Option 1"
Pop $RadioButton1
${NSD_CreateRadioButton} 10u 22u 60% 10u "&Option 2"
Pop $RadioButton2
${NSD_CreateRadioButton} 10u 32u 60% 10u "&Option 3"
Pop $RadioButton3
${NSD_CreateRadioButton} 10u 42u 60% 10u "&Option 4"
Pop $RadioButton4
nsDialogs::Show
FunctionEnd
Function nsDialogsPageLeave
${NSD_GetState} $RadioButton1 $RadioButton1_State
${NSD_GetState} $RadioButton2 $RadioButton2_State
${NSD_GetState} $RadioButton3 $RadioButton3_State
${NSD_GetState} $RadioButton4 $RadioButton4_State
${If} $RadioButton1_State == 1
${OrIf} $RadioButton2_State == 1
${OrIf} $RadioButton3_State == 1
${OrIf} $RadioButton4_State == 1
GetDlgItem $R0 $HWNDPARENT 1
EnableWindow $R0 1
Abort
${EndIf}
FunctionEnd
; License page
!insertmacro MUI_PAGE_LICENSE "License.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\AppMainExe.exe"
!insertmacro MUI_PAGE_FINISH
; Language files
!insertmacro MUI_LANGUAGE "English"
; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; MUI end ------
Name "menu test"
OutFile "Setup.exe"
InstallDir "$PROGRAMFILES\My application"
ShowInstDetails show
Section "MainSection" SEC01
;
SectionEnd The leave function is the wrong place to put that code. You need to setup an nsis function and setup an nsdialogs event that intercepts the radiobutton event, and that's where the code in the leave function should be (which makes the leave function empty).
There's a perfect example on how to do this: ${NSISDIR}\Examples\nsDialogs\example.nsi.
There's a perfect example on how to do this: ${NSISDIR}\Examples\nsDialogs\example.nsi.
Thank you very much Jason 🙂
i found that out shortly after posting, i just had to digg deeper 😉
im dealing now with another issue as a result of multiple choice install logic;
the uninstall needs a menu option selection in order to go through with proper uninstall,
i perform sectional install based on the radio selection later down the script;
then a global section after conditional $(if)'s selection exists,
the sectional uninstall then doesn't write exclusive instructions for each uninstaller;
the only way i found around it was to run the uninstaller part as a standalone outside the main installer script;
i moved the uninstall section to a script that only generates a setup with the specific uninstaller instructions for each one of the choices;
i then added the extracted uninstaller and used it as an external file added to the general install section of the choice;
completely removing uninstall section from the main installer script,
i know it's a crooked way to do this;
i couldn't come up with a better way to write the uninstaller so its specific through the main install script 😱
any advice?
TIA
Chris
i found that out shortly after posting, i just had to digg deeper 😉
im dealing now with another issue as a result of multiple choice install logic;
the uninstall needs a menu option selection in order to go through with proper uninstall,
i perform sectional install based on the radio selection later down the script;
then a global section after conditional $(if)'s selection exists,
the sectional uninstall then doesn't write exclusive instructions for each uninstaller;
the only way i found around it was to run the uninstaller part as a standalone outside the main installer script;
i moved the uninstall section to a script that only generates a setup with the specific uninstaller instructions for each one of the choices;
i then added the extracted uninstaller and used it as an external file added to the general install section of the choice;
completely removing uninstall section from the main installer script,
i know it's a crooked way to do this;
i couldn't come up with a better way to write the uninstaller so its specific through the main install script 😱
any advice?
TIA
Chris
You will have to store the config of the installation some way, either in the registry or as a config file (.ini). Then the uninstaller just reads this information back and executes the required parts, this way it's automatic and the user doesn't have to select a type during uninstall.
Thank you Jason 🙂
thats exactly the issue im trying to work around now,
i am storing some information in the registry atm;
mainly for add/remove to have a fancy entry that point to the uninstaller itself,
haven't had the pleasure of storing uninstall info in the reg yet;
unless these get their full current context path im not sure if its the right path?
(im also using wildcard for the main install process; not specific file names)
for now; i worked out 4 pre standalone silent installers;
these will batched prior to the main script; each outputs an option specific uninstaller data;
once these are executed locally (after they are compiled); the "fake installer" output the uninstaller to a specific directory; which is than used during the main process as a dedicated uninstaller,
from the main installer script; i removed all uninstall instructions;
i then added a direct uninstall.exe copy for each option selected (as part of the main its installer files),
they each hold the same conditional instructions i had before;
this way when the uninstall executes there are no issues or questions needed;
its not fancy; i use a simple KISS approach, a message alert with are you sure?
on OK; a wild card takes it all out in an instant; than exists,
(i just need to delete flat files; no hooks or any dependencies)
ATB
Chris,
thats exactly the issue im trying to work around now,
i am storing some information in the registry atm;
mainly for add/remove to have a fancy entry that point to the uninstaller itself,
haven't had the pleasure of storing uninstall info in the reg yet;
unless these get their full current context path im not sure if its the right path?
(im also using wildcard for the main install process; not specific file names)
for now; i worked out 4 pre standalone silent installers;
these will batched prior to the main script; each outputs an option specific uninstaller data;
once these are executed locally (after they are compiled); the "fake installer" output the uninstaller to a specific directory; which is than used during the main process as a dedicated uninstaller,
from the main installer script; i removed all uninstall instructions;
i then added a direct uninstall.exe copy for each option selected (as part of the main its installer files),
they each hold the same conditional instructions i had before;
this way when the uninstall executes there are no issues or questions needed;
its not fancy; i use a simple KISS approach, a message alert with are you sure?
on OK; a wild card takes it all out in an instant; than exists,
(i just need to delete flat files; no hooks or any dependencies)
ATB
Chris,
Alright, I'll try to keep this simple for you. The uninstaller is designed to uninstall everything, regardless of the configuration. All of this fancy add/remove stuff shouldn't be done in the uninstaller. Usually you have to copy the installer to the install directory, and have the 'add/remove' link point to the installer (I think there are extra values you can write to this part of the registry to change the available options in the 'Programs and Features' box).
In NSIS, it takes quite a bit more work to have an 'add/remove' feature implemented into the installer, as each component of the install has to have its status stored somewhere, and the installer needs dual 'File' and 'Delete' functions for every file depending on what's installed. Memento.nsh is designed partially for this purpose, though it can only add new sections to an install, it can't remove sections.
I would write an example but it's very time consuming to do so. Most programs these days just install everything that's needed. GIMP is one example, the first page has the 'Install' button and that's it.
I don't know how simple you are making this install, but it sounds pretty complicated to me.
In NSIS, it takes quite a bit more work to have an 'add/remove' feature implemented into the installer, as each component of the install has to have its status stored somewhere, and the installer needs dual 'File' and 'Delete' functions for every file depending on what's installed. Memento.nsh is designed partially for this purpose, though it can only add new sections to an install, it can't remove sections.
I would write an example but it's very time consuming to do so. Most programs these days just install everything that's needed. GIMP is one example, the first page has the 'Install' button and that's it.
I don't know how simple you are making this install, but it sounds pretty complicated to me.
Thank you Jason, you are very kind 🙂
there's no need to go to all this trouble for me;
though im sure other members would greatly appreciate a walk-through this situation;
its not the most elegant way to do things i guess;
so far i have my installer with the following flow
welcome screen ->
user name + serial key input ->
the key and email + product name are all validated online,
if validation fails 3 times; installer will exit, if the server responds OK we move on ->
license screen with back button disabled (to prevent re-validating key and user) ->
install option screen (4 different options); on select option Next button lights up ->
install option specific files with add/remove specific registry entries! ->
install complete screen ->
during selection i pass a unique name flag that carries through;
to differentiate uninstall registry strings for add/remove,
ex: ${PRODUCTNAME} ${OPTION}
each option has its own ${if} section to confine;
i do not write uninstall.exe or have uninstall section active in my main installer script;
instead i removed uninstall section and run it separately, something like this
(i batch run the 4 uninstall options scripts first; before the main installer script is build)
you will notice these silent script self destruct after they run once;
they extract the specific uninstaller to a unique folder;
these are dedicated uninstall.exe and are copied over on the main installer
through the option's ${if} statement; when the main installer completes building;
each option has a dedicated uninstaller copied over from the specific folder,
thats the only way around that NSIS limitation i could think of;
the uninstaller build has to be built externally to the main installer to preserve exclusive uninstall options
ATB,
Chris
Build.bat
there's no need to go to all this trouble for me;
though im sure other members would greatly appreciate a walk-through this situation;
its not the most elegant way to do things i guess;
so far i have my installer with the following flow
welcome screen ->
user name + serial key input ->
the key and email + product name are all validated online,
if validation fails 3 times; installer will exit, if the server responds OK we move on ->
license screen with back button disabled (to prevent re-validating key and user) ->
install option screen (4 different options); on select option Next button lights up ->
install option specific files with add/remove specific registry entries! ->
install complete screen ->
during selection i pass a unique name flag that carries through;
to differentiate uninstall registry strings for add/remove,
ex: ${PRODUCTNAME} ${OPTION}
each option has its own ${if} section to confine;
i do not write uninstall.exe or have uninstall section active in my main installer script;
instead i removed uninstall section and run it separately, something like this
(i batch run the 4 uninstall options scripts first; before the main installer script is build)
you will notice these silent script self destruct after they run once;
they extract the specific uninstaller to a unique folder;
these are dedicated uninstall.exe and are copied over on the main installer
through the option's ${if} statement; when the main installer completes building;
each option has a dedicated uninstaller copied over from the specific folder,
thats the only way around that NSIS limitation i could think of;
the uninstaller build has to be built externally to the main installer to preserve exclusive uninstall options
ATB,
Chris
Build.bat
:: build uninstallers
"D:\Program Files\NSIS3\makensis.exe" Uninstaller_OPT1.nsi
"D:\Program Files\NSIS3\makensis.exe" Uninstaller_OPT2.nsi
"D:\Program Files\NSIS3\makensis.exe" Uninstaller_OPT3.nsi
"D:\Program Files\NSIS3\makensis.exe" Uninstaller_OPT4.nsi
:: extract uninstallers
start Uninstall_Setup_OPT1.exe
start Uninstall_Setup_OPT2.exe
start Uninstall_Setup_OPT3.exe
start Uninstall_Setup_OPT4.exe
:: run the main installer build
"D:\Program Files\NSIS3\makensis.exe" Installer.nsi Uninstaller_OPT1.nsi# Company and product info
!define PRODUCT_NAME "PRODXYZ"
!define PRODUCT_VERSION "v1.0"
!define PRODUCT_LINE "MY PRODUCT"
!define COMPANYNAME "MY COMPANY"
# Option name
!define OPT1 "OPT1"
# Registry folder name prefix
!define OPT_1 "OPT1"
; MUI 1.67 compatible ------
!include "MUI.nsh"
; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Language files
!insertmacro MUI_DEFAULT MUI_PAGE_UNINSTALLER_PREFIX ""
!insertmacro MUI_LANGUAGE "English"
; MUI end ------
Name "Uninstall_Setup_OPT1"
OutFile "Uninstall_Setup_OPT1.exe"
ShowUnInstDetails nevershow
RequestExecutionLevel admin
Section -Post
WriteUninstaller "$EXEDIR\uninstall01\OPT1\uninstall.exe"
SectionEnd
Section Install
SelfDel::Del
SetAutoClose true
SectionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "${PRODUCT_LINE} - ${PRODUCT_NAME} ${PRODUCT_VERSION} ${OPT1} was successfully removed from your computer."
FunctionEnd
Function un.onInit
SetShellVarContext all
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove ${PRODUCT_LINE} - ${PRODUCT_NAME} ${PRODUCT_VERSION} ${OPT1} and all of its components?" IDYES +2
Abort
FunctionEnd
Section Uninstall
ReadRegStr $INSTDIR HKLM "SOFTWARE\${COMPANYNAME}\${PRODUCT_LINE} - ${PRODUCT_NAME} - ${OPT_1}" AppPath
# remove the Start Menu folder
rmDir /r "$SMPROGRAMS\${PRODUCT_LINE} - ${PRODUCT_NAME} ${PRODUCT_VERSION} ${OPT1}\"
# Remove Product information from the registry
DeleteRegKey HKLM "SOFTWARE\${COMPANYNAME}\${PRODUCT_LINE} - ${PRODUCT_NAME} - ${OPT_1}"
# Remove uninstaller information from the registry
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_LINE} - ${PRODUCT_NAME} ${PRODUCT_VERSION} ${OPT1}"
# Remove files
rmDir /r "$INSTDIR\${PRODUCT_LINE} - ${PRODUCT_NAME} ${PRODUCT_VERSION}"
SetAutoClose true
SectionEnd Oh, I see what's going on. So instead of building a single installer with all these different paths, I would build a single installer for each product, which would end up as four different installers and uninstallers. All of the pages except for the selection page (that I helped you out with) can be copied to each installer.
Then you can create a wrapper installer that bundles the four other installers, and this contains the selection page. This just extracts the required installer to $PLUGINSDIR. The wrapper installer can use RequestExecutionLevel User and ExecWait, plus HideWindow right before the ExeWait command.
So the wrapper installer script can make use of the '!if /FileExists' and '!makensis' commands to compile the four installers, and then they can be included in the script with File.
If you weren't using a selection page, then the wrapper would be different to what I said above.
Then you can create a wrapper installer that bundles the four other installers, and this contains the selection page. This just extracts the required installer to $PLUGINSDIR. The wrapper installer can use RequestExecutionLevel User and ExecWait, plus HideWindow right before the ExeWait command.
So the wrapper installer script can make use of the '!if /FileExists' and '!makensis' commands to compile the four installers, and then they can be included in the script with File.
If you weren't using a selection page, then the wrapper would be different to what I said above.
Thank you very much Jason, interesting approach 🙂
there's a drawback though; in that scenario ill be packing 4 times the required installed files?
Chris,
there's a drawback though; in that scenario ill be packing 4 times the required installed files?
Chris,
Can you run a test for me? Put 'SetCompress off' into your script, compile it, then post up the size details at the end of the compilation log.
im not actually packing files yet; if it make any difference, im working with ghost files for now,
(this little template im making will pack large files; 1-3GB+ easy (already compressed!))
(this little template im making will pack large files; 1-3GB+ easy (already compressed!))
EXE header size: 47616 / 34816 bytes
Install code: 43383 / 43379 bytes
Install data: 4708539 / 4708555 bytes
CRC (0xF0D8AFD6): 4 / 4 bytes
Total size: 4799542 / 4786754 bytes (100.2%) Well the test I just gave you is pointless then. The main reason for the test is to see how much of the data files have duplicates, which would mean the finished size would be a quarter of the uncompressed size.
You do know that NSIS has a 2GB single file limit right? I've already written a fork that uses an external file to store the data, and the external file can be up to 8EB big. Single files are still limited to 2GB.
You do know that NSIS has a 2GB single file limit right? I've already written a fork that uses an external file to store the data, and the external file can be up to 8EB big. Single files are still limited to 2GB.
Thank you Jason,
i had no idea; Ive been doing NSIS only the past two weeks now,
i haven't had a chance yet to learn about the 2Gb limit 🙁
Thx for HU 👍
ATB
Chris
i had no idea; Ive been doing NSIS only the past two weeks now,
i haven't had a chance yet to learn about the 2Gb limit 🙁
Thx for HU 👍
ATB
Chris