I have created customize page with two radio button for repair and remove.If the user select the repair button it goes for repair fun.but again come to old page that is repair and remove page.so the user selects both option.My requirement is user selects only one option and do corresponding actions only.No need to give the option to select both the buttons.
Function nsDialogpage
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateRadioButton} 0 5u 100% 10u "Repair"
Pop $Repair
${NSD_AddStyle} $Repair ${WS_GROUP}
${NSD_OnClick} $Repair Repair
${NSD_CreateRadioButton} 0 25u 100% 56u "Remove"
Pop $Remove
${NSD_OnClick} $Remove Remove
nsDialogs::Show
FunctionEnd
Function Repair
-- Do repair function.
FunctionEnd
Function Remove
ExecWait "$INSTDIR\uninstall.exe"
Quit
FunctionEnd
also if remove fun have remove the installer and quit the installation.
uninstaller has been done successfully.but installer again go main page after that user click any button then only quit from installation steps.
1.User select any one option and leave this repair and remove page.
2.If user click remove option remove the installer and immediately quit the process.
Quit does not quit right away when used in a page action callback, it will quit when the page changes. Performing some action when a radio button is clicked is not normal Windows behavior (Try pressing TAB) so I added a normal example aswell.
!include nsDialogs.nsh
Page Custom RepairOrRemovePageInsane_Create
Page Custom RepairOrRemovePageNormal_Create RepairOrRemovePageNormal_Leave
Page InstFiles
Function Remove
ExecWait '"cmd" /C echo This is a dummy uninstall command...&pause' ; Call real uninstaller here
FunctionEnd
Function Repair
# Do repair....
FunctionEnd
Function RepairOrRemovePageInsane_Create
nsDialogs::Create 1018
Pop $0
${NSD_CreateRadioButton} 0 5u 100% 10u "Repair"
Pop $0
SendMessage $HWNDPARENT ${WM_NEXTDLGCTL} $0 1
${NSD_OnClick} $0 RepairInsane
${NSD_CreateRadioButton} 0 25u 100% 56u "Remove"
Pop $0
${NSD_OnClick} $0 RemoveInsane
GetDlgItem $0 $hwndparent 1 ; Get Next button handle and
EnableWindow $0 0 ; ...disable it because it does not make sense with this insane radio button handling
nsDialogs::Show
FunctionEnd
Function RemoveInsane
Call Remove
SendMessage $HWNDPARENT ${WM_CLOSE} 0 0
FunctionEnd
Function RepairInsane
Call Repair
SendMessage $HWNDPARENT 0x408 1 0 ; Go to next page
FunctionEnd
Function RepairOrRemovePageNormal_Create
nsDialogs::Create 1018
Pop $1
${NSD_CreateRadioButton} 0 5u 100% 10u "Repair"
Pop $1
${NSD_CreateRadioButton} 0 25u 100% 56u "Remove"
Pop $2
SendMessage $1 ${BM_CLICK} 0 0 ; Select one of them by default
nsDialogs::Show
FunctionEnd
Function RepairOrRemovePageNormal_Leave
${NSD_GetState} $1 $0
${If} $0 <> 0
Call Repair
${Else}
Call Remove
Quit
${EndIf}
FunctionEnd
Related
I have a small bootstrapper with custom UI, which contains two pages, one to configure the install, and the other showing a progressbar for the download and install of the payload.
My problem:
If the user presses Enter key when in the second page, the installer exits, even if it didn't finish installing.
I removed all the controls I could from the UI with:
GetDlgItem $1 $HWNDPARENT 1 //(2, and 3)
System::Call `User32::DestroyWindow(i $1)`
in the onGuiInit function, and the first page ignores enter and space keys now, but the second page still exits on Enter key.
I have no other components on that page except some labels, a progressbar, and a slideshow (nsisSlideshow plugin).
In the background I have a thread which downloads and installs the payload.
The pages are declared like this:
Page Custom Options_Show Options_Leave
Page Custom Progress_Show Progress_Leave
So, long story short, when I press enter, the nsDialogs::Show function returns, killing the installer.
Any way I can stop it from doing this?
You really should try to stop forward page changes by calling Abort in the page leave callback function.
NSIS only blocks clicks from buttons that exist and are disabled.
!include nsDialogs.nsh
Page Custom Options_Show #Options_Leave
Page Custom Progress_Show #Progress_Leave
Function DisableBottomButtons
GetDlgItem $0 $hwndparent 1
ShowWindow $0 0
EnableWindow $0 0
GetDlgItem $0 $hwndparent 2
ShowWindow $0 0
EnableWindow $0 0
GetDlgItem $0 $hwndparent 3
ShowWindow $0 0
EnableWindow $0 0
FunctionEnd
Function Options_Show
nsDialogs::Create 1018
Pop $0
${NSD_CreateButton} 0 20 100% 12u "Go to next page"
Pop $0
${NSD_OnClick} $0 GoToNextPage
Call DisableBottomButtons
nsDialogs::Show
FunctionEnd
Function GoToNextPage
GetDlgItem $0 $hwndparent 1
EnableWindow $0 1
SendMessage $hwndparent ${WM_COMMAND} 1 0
FunctionEnd
Function Progress_Show
nsDialogs::Create 1018
Pop $0
${NSD_CreateButton} 0 20 100% 12u "Exit"
Pop $0
${NSD_OnClick} $0 ExitApp
Call DisableBottomButtons
nsDialogs::Show
FunctionEnd
Function ExitApp
MessageBox mb_ok "Bye"
; Faking a click on Next/Close will not work when the button is disabled,
; this uses a slightly ugly trick to bypass that. GoToNextPage does it properly.
!define /math WM_NOTIFY_OUTER_NEXT ${WM_USER} + 0x8
SendMessage $hwndparent ${WM_NOTIFY_OUTER_NEXT} 1 0
FunctionEnd
First, small code snippet:
!macro EnableNextButtonM IsEnable
Push $1
GetDlgItem $1 $HWNDPARENT 1 ;next button
EnableWindow $1 ${IsEnable}
Pop $1
!macroend
!define EnableNextButton "!insertmacro EnableNextButtonM"
Then, in function Progress_Show you should call
${EnableNextButton} 0
before
nsDialogs::Show
to disable Next button before it will be shown.
After download completion (at the download callback) call
${EnableNextButton} 1
to enable it again.
You variant with .onGuiInit does not work because it calls once - before first page will be shown. But every next page will be created dynamically again, thus, all UI page must be implemented into page custom -Pre function.
I need to make an installer that will also act as a repair/uninstall program if the concerned software is already installed.
I managed to make a custom page that check if the program exists and display buttons depending on that (the registry key creation is only for testing purpose and should be included in installation process).
For example, an Install button appears if the program isn't installed.
Here is the code doing this :
Page Custom MyCustomPage
var button
var buttonRepair
var buttonUninstall
var dialog
Function MyCustomPage
ReadRegStr $R0 HKLM ${P_DIR_REGKEY} "Version"
${If} ${Errors}
Goto NotInstalled
${Else}
Goto Installed
${EndIf}
NotInstalled:
nsDialogs::Create 1018
;Pop $dialog
${NSD_CreateButton} 25% 25% 50% 50% "Install"
Pop $button
EnableWindow $button 1 # start out disabled
WriteRegStr HKLM ${P_DIR_REGKEY} "Version" ${P_VERSION}
WriteRegStr HKLM ${P_DIR_REGKEY} "" "$INSTDIR\asd.exe"
nsDialogs::Show
${NSD_OnClick} $button ManageInstall
Goto MyEnd
Installed:
nsDialogs::Create 1018
Pop $0
${NSD_CreateButton} 12% 12% 25% 25% "Repair"
Pop $buttonRepair
${NSD_CreateButton} 37% 12% 25% 25% "Uninstall"
Pop $buttonUninstall
EnableWindow $button 1 # start out disabled
EnableWindow $button2 1
${NSD_OnClick} $buttonRepair ManageRepair
${NSD_OnClick} $buttonUninstall ManageUninstall
nsDialogs::Show
Goto MyEnd
MyEnd:
Quit
FunctionEnd
Function ManageInstall
MessageBox MB_OK "Installation"
FunctionEnd
Function ManageRepair
MessageBox MB_OK "Repair"
FunctionEnd
Function ManageUninstall
MessageBox MB_OK "Uninstallation"
FunctionEnd
The problem is that it's all managed by functions, and I can't declare new pages macros in them, so I can't continue with the proper installation through sections because of it.
How should I manage the different actions to be taken by the installer to be able to make user friendly pages like a normal install ?
Should I use custom pages for every single action, because it sounds a bit fastidious and complicated ?
I recommend you create a variable named "ACTION", and set its value when the user clicks an option. And then, jump to the next page. Something like this:
# http://nsis.sourceforge.net/Go_to_a_NSIS_page
Function RelGotoPage
IntCmp $R9 0 0 Move Move
StrCmp $R9 "X" 0 Move
StrCpy $R9 "120"
Move:
SendMessage $HWNDPARENT "0x408" "$R9" ""
FunctionEnd
Function GotoNextPage
StrCpy $R9 "1"
Call RelGotoPage
FunctionEnd
Function ManageRepair
StrCpy $ACTION "repair"
Call GotoNextPage
Abort
FunctionEnd
Then, on each page's "pre" function, you need to check it it has to be displayed or not:
Function repairpage
# Do not display this page unless user selected Repair.
${if} "$ACTION" != "repair"
Abort
$[EndIf}
....
FunctionEnd
I want to create a Textinput for the User dynamically depending from the State of a Checkbox above it.
I tried something like this:
...
Function nsDialogsPage
nsDialogs::Create 1018
${NSD_CreateCheckBox} 20u 55u 50% 20u "Download with Proxy"
Pop $testBox
${NSD_OnClick} $testBox button_click
nsDialogs::Show
FunctionEnd
Function button_click
${NSD_GetState} $testBox $6
${If} $6 == 1
${NSD_CreateText} 20u 75u 80% 25p "Enter your Proxy ..."
${Else}
;Remove the Text, Set it invisible or do something like this ...
${EndIf}
FunctionEnd
Function nsDialogsPageLeave
;does something with the input
FunctionEnd
I didn't find anything on http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html and
I dont know how to remove the Box or make it invisible for the User or something like this, that he can't enter anything when the CheckBox is unchecked.
Take a look at EnableWindow
${NSD_CreateText} 20u 75u 80% 25p "Enter your Proxy ..."
Pop $myText
#disable control
EnableWindow $myText 0
#enable control
EnableWindow $myText 1
#hide control
ShowWindow $myText 0
#show control
ShowWindow $myText 1
I have used nsis script for creating installer.When i run my installer second time with same name,REPAIR and REMOVE should be check and do the corresponding operation.I have find out my application already installed or not using following codes,
Function checkinstall
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\My app" "UninstallString"
IfFileExists $R0 +1 NotInstalled
call nsDialogpage
NotInstalled:
FunctionEnd
Function nsDialogpage
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateRadioButton} 0 5u 100% 10u "Repair"
Pop $hwnd
${NSD_AddStyle} $hwnd ${WS_GROUP}
${NSD_OnClick} $hwnd ???
${NSD_CreateRadioButton} 0 25u 100% 56u "Remove"
Pop $hwnd
${NSD_OnClick} $hwnd ???
nsDialogs::Show
If the user select repair button it should overwrites existing installation path else uninstall existing installed and continue with new one.what am i need do to replace the (???) of the above code
page custom checkinstall
!insertmacro MUI_PAGE_DIRECTORY
My next page is Directory selection.so i need to call this page? How to achieve this?
1.How can i call un installer function if the user selects remove button?
Function un.Init, section /o -un.Main UNSEC000,section -un.post UNSE001
these are the un installer funtions.How can i call these functions? i have tried call method but it did not work.
You need to specify a callback function, like in the nsDialogs documentation, look for the nsDialogsPageLeave function in this example:
!include nsDialogs.nsh
!include LogicLib.nsh
Name nsDialogs
OutFile nsDialogs.exe
XPStyle on
Var Dialog
Var Label
Var Text
Page custom nsDialogsPage nsDialogsPageLeave
Page instfiles
Function nsDialogsPage
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
Pop $Label
${NSD_CreateText} 0 13u 100% -13u "Type something here..."
Pop $Text
${NSD_OnChange} $Text nsDialogsPageTextChange
nsDialogs::Show
FunctionEnd
Function nsDialogsPageLeave
${NSD_GetText} $Text $0
MessageBox MB_OK "You typed:$\n$\n$0"
FunctionEnd
Function nsDialogsPageTextChange
Pop $1 # $1 == $ Text
${NSD_GetText} $Text $0
${If} $0 == "hello"
MessageBox MB_OK "right back at ya!"
${EndIf}
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
Incase of custom pages in NSIS script is there any way to retain the data entered by user when back button is pressed (when the installer is running)?
There are a couple of ways to do this. Either way you need to store your data in globals.
1) Use a "Leave" function.
Page custom EnterCustom LeaveCustom
; Create two variables for each value/widget pair
Var Text
Var TextWidget
Var Check
Var CheckWidget
Function EnterCustom
nsDialogs::Create 1018
Pop $0
${NSD_CreateText} 0 0 80u 12u $Text
Pop $TextWidget
${NSD_CreateCheckBox} 0 26u 80u 12u "Check this box"
Pop $CheckWidget
${NSD_SetState} $CheckWidget $Check
nsDialogs::Show
FunctionEnd
Function LeaveCustom
${NSD_GetText} $TextWidget $Text
${NSD_GetState} $CheckWidget $Check
FunctionEnd
The only problem with this method is that LeaveCustom only gets called if you hit the next button. So if you edit the fields then click the Back button your changes are lost. The changes are however saved if you go forward then come back.
2) Use the OnChange callback.
This is a little more complicated but solves the problem with the previous method.
Page custom EnterCustom
Var Initialized
; Create two variables for each value/widget pair
Var Text
Var TextWidget
Var Check
Var CheckWidget
Function EnterCustom
nsDialogs::Create 1018
Pop $0
${If} $Initialized != "True"
; Set defaults for all your values here
StrCpy $Text "Initial Value"
StrCpy $Check ${BST_UNCHECKED}
StrCpy $Initialized "True"
${EndIf}
; Create and configure all of your widgets
${NSD_CreateText} 0 0 80u 12u $Text
Pop $TextWidget
${NSD_OnChange} $TextWidget OnTextChange
${NSD_CreateCheckBox} 0 26u 80u 12u "Check this box"
Pop $CheckWidget
${NSD_SetState} $CheckWidget $Check
${NSD_OnClick} $CheckWidget OnCheckClick
nsDialogs::Show
FunctionEnd
; Create a callback function for each Widget
Function OnTextChange
Pop $0 ; Widget handle is on stack
${NSD_GetText} $TextWidget $Text
FunctionEnd
Function OnCheckClick
Pop $0 ; Widget handle is on stack
${NSD_GetState} $CheckWidget $Check
FunctionEnd
Some widgets, e.g. RadioButtons and CheckBoxes, use the OnClick function instead. Also the ComboBox does not work well with this method. However, a DropList, which does not seem to be documented, can usually replace it and works fine.
Radio buttons are also a little tricky because only the click callback for the selected button is called. I solved this by updating all of the radio button values in each radio button click callback.
Messy/tedious but it works.
I know it's an old question, but I've landed here from my googling.
You can use NSD_OnBack (or call nsDialogs::OnBack directly) to set OnBack callback.
Here is the code snipet:
Function portsSelectionPage
nsDialogs::Create 1018
Pop $0
${NSD_CreateNumber} 70u 0 40u 12u $TomcatPort
Pop $TomcatPortHWND
${NSD_CreateNumber} 70u 14u 40u 12u $PostgresPort
Pop $PostgresPortHWND
nsDialogs::Show
${NSD_OnBack} "portsSelectionPageLeave"
FunctionEnd
Function portsSelectionPageLeave
${NSD_GetText} $TomcatPortHWND $TomcatPort
${NSD_GetText} $PostgresPortHWND $PostgresPort
FunctionEnd
You can store data in a global variable, or in a .ini in $pluginsdir
!include nsDialogs.nsh
!include LogicLib.nsh
Name nsDialogs
OutFile nsDialogs.exe
XPStyle on
Var Dialog
Var Label
Var Text
Var Text_State
Var Checkbox
Var Checkbox_State
Page custom nsDialogsPage nsDialogsPageLeave
Page license
Page instfiles
Function .onInit
StrCpy $Text_State "Type something here..."
FunctionEnd
Function nsDialogsPage
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 12u "Hello, welcome to nsDialogs!"
Pop $Label
${NSD_CreateText} 0 13u 100% 12u $Text_State
Pop $Text
${NSD_CreateCheckbox} 0 30u 100% 10u "&Something"
Pop $Checkbox
${If} $Checkbox_State == ${BST_CHECKED}
${NSD_Check} $Checkbox
${EndIf}
# alternative for the above ${If}:
#${NSD_SetState} $Checkbox_State
nsDialogs::Show
FunctionEnd
Function nsDialogsPageLeave
${NSD_GetText} $Text $Text_State
${NSD_GetState} $Checkbox $Checkbox_State
FunctionEnd
Section
DetailPrint "hello world"
SectionEnd
more information http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html#step-memory