Making a password work - nsis

So what you gave me works great.
Now the question is how do I set it so the password page has a message on it asking for you to inter your password This is what I have so far.
Function leave
${NSD_GetText} $hwnd $0
${If} $0 != "web9^root"
MessageBox MB_OK "Please enter a valid security code"
Abort
${EndIf}
FunctionEnd
Function pre
nsDialogs::Create 1018
Pop $dialog
${NSD_CreatePassword} 0 0 50% 8% ""
Pop $hwnd
nsDialogs::show
FunctionEnd
======================
so i have the following script set up to run,
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
OutFile "test.exe"
Page Custom pre
var dialog
var hwnd
Function pre
nsDialogs::Create 1018
Pop $dialog
${NSD_CreatePassword} 0 0 50% 8% "web9^root"
Pop $hwnd
SendMessage $hwnd ${EM_SETPASSWORDCHAR} 149 0 # 149 = medium dot
nsDialogs::Show
FunctionEnd
Section ""
SectionEnd
How do I make it so that if you do not know the password it will not let you pass. I also need to know who to set it so that the password is not already in the text feild. Can you all help me with this

you will have to add a leave function for that nsdialogs page...
Page custom pre leave
...and there you verify the password...
Function leave
${NSD_GetText} $hwnd $0
${If} $0 != "yourPassword"
MessageBox MB_OK "Wrong password"
Abort
${EndIf}
FunctionEnd
if you don't want the password in that field, just leave it empty when creating the dialog!

Related

NSIS: How do I allow multiple user choice screens that select the sections to install?

I'm attempting to create an installer that asks the user a series of questions to decide which components to install. Each choice (potentially) influences the available options in later choices (else I would just do a normal components page—I don't want to give the user invalid options).
How do I accomplish such a thing? If I just use the components page, all the options are shown, some combinations of which are completely invalid. I don't want to let the user select those. Is it possible to leave out the components page?
Here's a minimal working example of what I'm trying. (Sorry it's long, I couldn't really simplify the dialog code.)
!include nsDialogs.nsh
!include Sections.nsh
Name "mwe"
OutFile "mwe.exe"
InstallDir C:\mwe
Var hwnd
Var Level1Opt
Page custom SelectLevel1Opt ProcessLevel1
Function SelectLevel1Opt
nsDialogs::Create 1018
pop $hwnd
${NSD_CreateLabel} 0 0 100% 12u "Please select level 1 option"
Pop $hwnd
${NSD_CreateRadioButton} 10% 12u 100% 12u "Level 1 A"
Pop $hwnd
nsDialogs::SetUserData $hwnd "Level 1 A"
${NSD_OnClick} $hwnd SetLevel1
${NSD_CreateRadioButton} 10% 24u 100% 12u "Level 1 B"
Pop $hwnd
nsDialogs::SetUserData $hwnd "Level 1 B"
${NSD_OnClick} $hwnd SetLevel1
nsDialogs::Show
FunctionEnd
Function SetLevel1
Pop $hwnd
nsDialogs::GetUserData $hwnd
Pop $Level1Opt
MessageBox MB_OK "Selected: $Level1Opt"
FunctionEnd
Function ProcessLevel1
${If} $Level1Opt == "Level 1 A"
!insertmacro SelectSection Level1A
${ElseIf} $Level1Opt == "Level 1 B"
!insertmacro SelectSection Level1B
${EndIf}
FunctionEnd
Page directory
Page instfiles
Section ""
MessageBox MB_OK "Common Install"
SectionEnd
Section /o "" Level1A
MessageBox MB_OK "Level 1 A"
SectionEnd
Section /o "" Level1B
MessageBox MB_OK "Level 1 B"
SectionEnd
No matter what I choose, neither Level1A nor Level1B sections get run. The selection from the dialog is correctly detected in the handler and the post function. However, selecting the sections isn't causing them to run. Even if I add a components page, neither of them is selected.
I looked in Selection.nsh, and the example it refers to (one-section.nsi) doesn't really do what I want, because it uses the components page. (I also don't understand quite how it works.)
What am I doing wrong? In what way am I misunderstanding the way NSIS is supposed to work?
As idleberg says, the correct syntax is !insertmacro SelectSection ${Level1A} but you get a warning because the section id is not defined until after its Section instruction in your .nsi. You need to move the functions that use ${Level1A} below the sections in your source code:
!include nsDialogs.nsh
!include Sections.nsh
Page custom SelectLevel1Opt ProcessLevel1
Page instfiles
Section ""
MessageBox MB_OK "Common Install"
SectionEnd
Section /o "a" Level1A
MessageBox MB_OK "Level 1 A"
SectionEnd
Section /o "b" Level1B
MessageBox MB_OK "Level 1 B"
SectionEnd
Var hInnerDialog
Var hL1A
Var hL1B
Function SelectLevel1Opt
nsDialogs::Create 1018
pop $hInnerDialog
${NSD_CreateLabel} 0 0 100% 12u "Please select level 1 option"
Pop $0
${NSD_CreateRadioButton} 10% 12u 100% 12u "Level 1 A"
Pop $hL1A
nsDialogs::SetUserData $hL1A ${Level1A} ; Only used by the generic function
${NSD_CreateRadioButton} 10% 24u 100% 12u "Level 1 B"
Pop $hL1B
nsDialogs::SetUserData $hL1B ${Level1B} ; Only used by the generic function
nsDialogs::Show
FunctionEnd
Function ProcessLevel1
${NSD_GetState} $hL1A $1
${If} $1 <> ${BST_UNCHECKED}
!insertmacro SelectSection ${Level1A}
!insertmacro UnselectSection ${Level1B}
${Else}
!insertmacro SelectSection ${Level1B}
!insertmacro UnselectSection ${Level1A}
${EndIf}
FunctionEnd
The ProcessLevel1 function can also be implemented as a loop if there are many radio buttons:
Function ProcessLevel1
StrCpy $0 ""
loop:
FindWindow $0 "${__NSD_RadioButton_CLASS}" "" $hInnerDialog $0
System::Call "USER32::GetWindowLong(p$0,i${GWL_STYLE})i.r1"
IntOp $1 $1 & ${BS_AUTORADIOBUTTON}
${If} $1 = ${BS_AUTORADIOBUTTON} ; Is it a auto radio button?
nsDialogs::GetUserData $0 ; Get the section id
Pop $2
${NSD_GetState} $0 $1
${If} $1 <> ${BST_UNCHECKED}
!insertmacro SelectSection $2
${Else}
!insertmacro UnselectSection $2
${EndIf}
${EndIf}
IntCmp $0 0 "" loop loop
FunctionEnd

Jump to Next Page

I am trying to jump forward 1 page in my installer. I have a custom page in my NSIS installer. This custom page prompts the user to input a serial number. If they are valid I will jump the installer forward to the next page (the welcome page) if not we remain on the page. I will be jumping to the next page from within both the Initialse and Finalise functions.
Every time I try to jump to the next page the installer just closes. I have tried Abort and Return but both cause the installer to close. I have also trid Call RelGoToPage where $R9 is 1 but this sends the user back the page they are already on, ie, an infinite loop.
Whats going wrong and how can I make my installer jump to the next page.
# Page Definition
Page Custom SerialPageInitialise SerialPageFinalise
# Page Implementation
Function SerialPageInitialise
!insertmacro ValidateSUser
${If} $isValidUser > 0 # If user if valid
Return # Go to next page...Doesn't work just closes the whole installer
#Abort # Doesn't work just closes the whole installer
${EndIf}
FunctionEnd
# For the following function: the message "A" always shows then the installer closes
Function SerialPageFinalise
${NSD_GetText} $SerialEditBx $R9
!insertmacro ValidateUserExpanded "$R9"
${If} $isValidUser > 0 # If user if valid
MessageBox MB_OK "A"
${Else}
MessageBox MB_OK|MB_ICONEXCLAMATION "Authentication Failed. You are not a recognised client."
Abort
${EndIf}
FunctionEnd
Works fine for me:
!include LogicLib.nsh
!include nsDialogs.nsh
var isValidUser
var SerialEditBx
!macro ValidateUserExpanded param
StrCpy $isValidUser 0
${If} ${param} = 666
StrCpy $isValidUser 1
${EndIf}
!macroend
!macro ValidateSUser
MessageBox mb_yesno "ValidateSUser?" IDNO nope
!insertmacro ValidateUserExpanded 666
nope:
!macroend
Function SerialPageInitialise
!insertmacro ValidateSUser
${If} $isValidUser > 0
Abort ; Skip page
${EndIf}
nsDialogs::Create 1018
Pop $0
${NSD_CreateText} 0 13u 50% 13u "667"
Pop $SerialEditBx
nsDialogs::Show
FunctionEnd
Function SerialPageFinalise
${NSD_GetText} $SerialEditBx $R9
!insertmacro ValidateUserExpanded "$R9"
${If} $isValidUser > 0 # If user if valid
MessageBox MB_OK "OK"
${Else}
MessageBox MB_OK|MB_ICONEXCLAMATION "Authentication Failed. You are not a recognised client."
Abort ; Don't allow going to next page
${EndIf}
FunctionEnd
Page Custom SerialPageInitialise SerialPageFinalise
Page InstFiles

Label or text box

So this is what I have for password set up. I would like to know how I make it so that the page has a lable or text box on it that Askes you to enter a password. As of rigth now it is blank. any ideas
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
Page Custom pre leave
var dialog
var hwnd
Function leave
${NSD_GetText} $hwnd $0
${If} $0 != "Password"
MessageBox MB_OK "Please enter a valid Security Code"
Abort
${EndIf}
FunctionEnd
Function pre
nsDialogs::Create 1018
Pop $dialog
${NSD_CreatePassword} 0 0 50% 8% ""
Pop $hwnd
SendMessage $hwnd ${EM_SETPASSWORDCHAR} 149 0 # 149 = medium dot
nsDialogs::show
FunctionEnd
...
${NSD_CreateLabel} 0 2d 70d 16d "Password:"
Pop $0
${NSD_CreatePassword} 70d 0 50% 20d ""
Pop $hwnd
...

How to use REMOVE or REPAIR feature in NSIS script?

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

Retain data on custom pages when back button is pressed

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

Resources