NSIS script + Skip button alignment issue - nsis

I am trying NSIS script to add "SKIP" button.
I have tested below code and it works well but when I actually integrate with the main code which is having a screen of option "back" "Next" and "Cancel" button. this skip button is not visible at all, it is in extreme right of cancel button and hardly visible.
How can move this "Skip" button towards left side.
Name BtnTest
Outfile test.exe
Installdir "$temp"
RequestExecutionLevel user
BrandingText " " ;Button covers this text
!include nsDialogs.nsh ;For WS_*
!define MUI_CUSTOMFUNCTION_GUIINIT SKIP
Function SKIP
; You are supposed to use ChangeUI (or MUI_UI) and a modified ui file to add new buttons but this example adds the button at run-time...
GetDlgItem $0 $hwndparent 2 ; Find cancel button
System::Call *(i,i,i,i)i.r1
System::Call 'USER32::GetWindowRect(ir0,ir1)'
System::Call *$1(i.r2,i.r3,i.r4,i.r5)
IntOp $5 $5 - $3 ;height
IntOp $4 $4 - $2 ;width
System::Call 'USER32::ScreenToClient(i$hwndparent,ir1)'
System::Call *$1(i.r2,i.r3)
System::Free $1
IntOp $2 $2 + $4 ;x
IntOp $2 $2 + 8 ;x+padding
System::Call 'USER32::CreateWindowEx(i0,t "Button",t "Click Me",i${WS_CHILD}|${WS_VISIBLE}|${WS_TABSTOP},ir2,ir3,ir4,ir5,i $hwndparent,i 0x666,i0,i0)i.r0'
SendMessage $hwndparent ${WM_GETFONT} 0 0 $1
SendMessage $0 ${WM_SETFONT} $1 1
GetFunctionAddress $0 onmybtnclick
ButtonEvent::AddEventHandler 0x666 $0
FunctionEnd
Function onmybtnclick
MessageBox mb_ok "You clicked me!"
FunctionEnd
Page Directory
Page Instfiles
Section
SectionEnd
And also this button appears on all screen How can I display only in one screen.

Change $2 and $3 before the call to CreateWindowEx to change the button position. You can save the handle to the button in another variable after CreateWindowEx but I just used the Id in this example (0x666).
Name BtnTest
Outfile test.exe
Installdir "$temp"
RequestExecutionLevel user
BrandingText " " ;Button covers this text
!include nsDialogs.nsh ;For WS_*
!define MUI_CUSTOMFUNCTION_GUIINIT SKIP
/**/ !include MUI2.nsh #*/
!ifndef MUI_INCLUDED
Function .onGuiInit
Call SKIP
FunctionEnd
!endif
Function SKIP
; You are supposed to use ChangeUI (or MUI_UI) and a modified ui file to add new buttons but this example adds the button at run-time...
GetDlgItem $0 $hwndparent 2 ; Find cancel button
System::Call *(i,i,i,i)i.r1
System::Call 'USER32::GetWindowRect(ir0,ir1)'
System::Call *$1(i.r2,i.r3,i.r4,i.r5)
IntOp $5 $5 - $3 ;height
IntOp $4 $4 - $2 ;width
System::Call 'USER32::ScreenToClient(i$hwndparent,ir1)'
System::Call *$1(i.r2,i.r3)
System::Free $1
!ifdef MUI_INCLUDED
StrCpy $2 15 ; Whatever you feel looks good
!else
IntOp $2 $2 + $4 ;x
IntOp $2 $2 + 8 ;x+padding
!endif
System::Call 'USER32::CreateWindowEx(i0,t "Button",t "Click Me",i${WS_CHILD}|${WS_VISIBLE}|${WS_TABSTOP},ir2,ir3,ir4,ir5,i $hwndparent,i 0x666,i0,i0)i.r0'
SendMessage $hwndparent ${WM_GETFONT} 0 0 $1
SendMessage $0 ${WM_SETFONT} $1 1
GetFunctionAddress $0 onmybtnclick
ButtonEvent::AddEventHandler 0x666 $0
FunctionEnd
Function onmybtnclick
MessageBox mb_ok "You clicked me!"
FunctionEnd
Function HideIt
GetDlgItem $0 $hwndparent 0x666
ShowWindow $0 0
FunctionEnd
Function ShowIt
GetDlgItem $0 $hwndparent 0x666
ShowWindow $0 1
FunctionEnd
!ifdef MUI_INCLUDED
!define MUI_PAGE_CUSTOMFUNCTION_SHOW HideIt
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ShowIt
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_SHOW HideIt
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE English
!else
Page Components "" HideIt
Page Components "" ShowIt
Page Components "" HideIt
Page Instfiles
!endif
Section
SectionEnd

Related

NSIS script doesn't display service status

I created section at the end of script which suppose to display myservice status, but no messagebox displays after exec.
What might be the reason?
Section "Create Service"
ExecShellWait '' 'sc.exe' 'create myservice error= "severe" displayname= "myservice" type= "own" start= "auto" binpath= "$INSTDIR\MyService.exe"' SW_HIDE
SectionEnd
Section "Start Service"
ExecShellWait '' 'sc.exe' 'start myservice' SW_HIDE
SectionEnd
Section "Ensure Running"
StrCpy $R0 '"$SYSDIR\cmd.exe" /c "sc QUERY myservice | FIND /C "RUNNING""'
nsExec::ExecToStack '$R0'
Pop $R1 # contains return code
Pop $R2 # contains output
${If} $R1 == "0"
DetailPrint "checking if command is success"
${If} $R2 == "1"
MessageBox mb_ok "myservice is Running" # it's running
${Else}
MessageBox mb_ok "Not Running" # it's not running
${EndIf}
${Else}
DetailPrint "command failed"
${EndIf}
SectionEnd ```
nsExec::ExecToStack /OEM '$R0' didn't change anything. During installation it rushes to finish page after sc exec ..Do I need to add additional page page here ?
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE ..\license.rtf
; Page custom pageRegistration
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Without seeing the output I can only guess that there is some sort of Unicode issue.
Change nsExec::ExecToStack '$R0' to nsExec::ExecToStack /OEM '$R0'.
That being said, I don't know if the RUNNING string is always in English. There are several service plug-ins and macros on the NSIS wiki you can use instead.
Or you can use this:
!include "LogicLib.nsh"
!include "Win\COM.nsh"
!include "Win\Propkey.nsh"
Function IsServiceRunning
Exch $0
Push $1
StrCpy $1 $0
!insertmacro ComHlpr_CreateInProcInstance {13709620-C279-11ce-A49E-444553540000} {A4C6892C-3BA9-11D2-9DEA-00C04FB16162} r0 "" ; IE5+?
${If} $0 P<> 0
System::Call "$0->36(wr1,#r1)i.s"
${IUnknown::Release} $0 ""
Pop $0
${If} $0 >= 0
StrCpy $0 0
Push $2
${V_GetVT} $1 r2
${V_GetBOOL} $1 r1
${If} $2 = ${VT_BOOL}
${AndIf} $1 <> ${VARIANT_FALSE}
StrCpy $0 1
${EndIf}
Pop $2
${Else}
StrCpy $0 0
${EndIf}
${EndIf}
Pop $1
Exch $0
FunctionEnd
Section "Example"
Push "RemoteRegistry"
Call IsServiceRunning
Pop $0
DetailPrint "RemoteRegistry running=$0"
Push "Themes"
Call IsServiceRunning
Pop $0
DetailPrint "Themes running=$0"
SectionEnd

How to move NSD_OnBack function from the section in NSIS

I'm writing an NSIS script, in this using some sections to execute EXE files. on depending output, I need to go back from the section to other custom pages but here nsis is moving to another section even though keeping of NSD_OnBack function or just calling the particular function
I have tried below 2 methods.
${NSD_OnBack} "callbackfunction"
call callbackfunction
//Section started
Section "validation" VALIDATION
DetailPrint "Executing Validation"
File "Folder_name\Validation.exe"
nsExec::Exec '"$INSTDIR\Validation.exe" $arg1 $arg2 $arg3'
IfFileExists "$INSTDIR\Output.txt" pass fail
pass:
FileOpen $chk "$INSTDIR\Output.txt" r
FileRead $chk $1
MessageBox MB_OK|MB_ICONSTOP "Validation_Output : in 1 $1"
Push $1
Push "true"
Call StrContains
Pop $3
${If} $3 == "true"
call someotherfunction
${ELSE}
goto fail
${ENDIF}
FileClose $chk
Delete $chk
fail:
MessageBox MB_OK|MB_ICONSTOP "fail"
//Here this call is not working
${NSD_OnBack} "callbackfunction"
SectionEnd
Function callbackfunction
GetDlgItem $0 $HWNDPARENT 2
${IF} $portalname == "centralised"
${IF} $username == ""
call CentralisedPage
${ENDIF}
${ELSE}
${IF} $username == ""
call SetCustom
${ENDIF}
${ENDIF}
Functionend
I am expecting to move other page based on EXE results.
${NSD_OnBack} is a callback for nsDialogs custom pages and it is invoked when the user presses the back button on that page, it is not relevant here.
Ideally you should collect all information before you get to the InstFiles page but if you can't do that then I would recommend that you just show a custom page after the InstFiles page if required.
If you absolutely need to execute sections multiple times you can use more than one InstFiles page:
!include LogicLib.nsh
!include WinMessages.nsh
!include nsDialogs.nsh
!include Sections.nsh
!include MUI2.nsh
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_PRE Init1stStage
!insertmacro MUI_PAGE_INSTFILES
Page Custom MyCustomPageCreate
!define MUI_PAGE_CUSTOMFUNCTION_PRE Init2ndStage
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
Var Needs2ndStage
Section "1st stage" SID_1
DetailPrint "1st stage"
MessageBox mb_yesno "Needs 2nd stage?" IDNO nope
StrCpy $Needs2ndStage 1
nope:
SectionEnd
Section "-2nd stage" SID_2
DetailPrint "2nd stage"
SectionEnd
Function Init1stStage
!insertmacro UnselectSection ${SID_2}
FunctionEnd
Function Init2ndStage
!insertmacro UnselectSection ${SID_1}
${IfThen} $Needs2ndStage = 0 ${|} Abort ${|}
FunctionEnd
Function MyCustomPageCreate
${IfThen} $Needs2ndStage = 0 ${|} Abort ${|}
!insertmacro SelectSection ${SID_2}
GetDlgItem $0 $hWndParent 1
SendMessage $0 ${WM_SETTEXT} "" "STR:C&ontinue"
GetDlgItem $0 $hWndParent 3
ShowWindow $0 0 ; Hide back
GetDlgItem $0 $hWndParent 2
EnableWindow $0 0 ; Disable cancel
!insertmacro MUI_HEADER_TEXT "Blah" "Blah blah blah"
nsDialogs::Create 1018
Pop $0
${NSD_CreateLabel} 0 0 100% 12u "Enter blah blah before you can enter the 2nd stage"
Pop $0
nsDialogs::Show
FunctionEnd

Set run-time cursor position in directory page dialog box - NSIS

I want to add at the end of the path the installation folder name of my App. I do it successfully after clicking the Browse button but, after many tentatives, I couldn't do it if I modify the text directly in the textbox.
Function .onVerifyInstDir
Push $0
FindWindow $0 "#32770" "" $HWNDPARENT
GetDlgItem $0 $0 0x3FB
;in alternative for MUI >2.0 I could use directly $mui.DirectoryPage.Directory. Is it right?
;does path end with "\MyApp"?
StrLen $R1 "\${APP_FOLDER_NAME}"
StrCpy $R0 $INSTDIR "" -$R1
StrCmp $R0 "\${APP_FOLDER_NAME}" +2
;add "\MyApp" after browse button clicking (OK)
StrCpy $INSTDIR "$INSTDIR\${APP_FOLDER_NAME}"
;add "\MyApp" after typing directly into the textbox but the cursor position reset to the first character. Tried to solve saving the current cursor position and then reapply it (NOK)
SendMessage $0 ${EM_GETSEL} null $1
SendMessage $0 ${WM_SETTEXT} 0 "STR:$INSTDIR"
SendMessage $0 ${EM_SETSEL} $1 $1
FunctionEnd
I don't succeed of mantain the cursor where I'm modifying the path string and it reset always to the first char.
In a previous phase of install process I initialise the Install path as follow
StrCpy $INSTDIR "$APPDATA\${APP_FOLDER_NAME}"
NSIS is supposed to do this for you already.
From the docs:
... the part of this string following the last \ will be used if the user selects 'browse', and may be appended back on to the string at install time (to disable this, end the directory with a \ (which will require the entire parameter to be enclosed with quotes). If this doesn't make any sense, play around with the browse button a bit.
Meaning,
InstallDir "$ProgramFiles\MyApp"
is not the same as
InstallDir "$ProgramFiles\MyApp\"
Setting the text in .onVerifyInstDir is not officially supported but this code somewhat works:
!define APP_FOLDER_NAME MyApp
Page Directory
Page InstFiles
!include WinMessages.nsh
!include LogicLib.nsh
Function .onInit
StrCpy $INSTDIR "$APPDATA\${APP_FOLDER_NAME}"
FunctionEnd
Var InOnVerifyInstDir
Var SeenModal
Function .onVerifyInstDir
${IfThen} $InOnVerifyInstDir <> 0 ${|} Return ${|} ; Don't recurse into .onVerifyInstDir
!if ${MUI_SYSVERSION} >= 2.0
StrCpy $0 $mui.DirectoryPage.Directory
!else
FindWindow $0 "#32770" "" $hWndParent
GetDlgItem $0 $0 0x3FB
!endif
System::Call 'USER32::GetActiveWindow()p.r2'
System::Call 'USER32::GetFocus()p.r1'
${If} $1 P<> $0
${If} $hWndParent P<> $2
StrCpy $SeenModal 1
Return
${EndIf}
${If} $SeenModal = 0
Return
${EndIf}
${EndIf}
StrCpy $SeenModal ""
;does path end with "\MyApp"?
StrLen $R1 "\${APP_FOLDER_NAME}"
StrCpy $R0 $INSTDIR "" -$R1
${If} $R0 != "\${APP_FOLDER_NAME}"
StrCpy $InOnVerifyInstDir 1
StrCpy $INSTDIR "$INSTDIR\${APP_FOLDER_NAME}"
SendMessage $0 ${EM_GETSEL} "" "" $1
IntOp $1 $1 >> 16 ; shift hiword
IntOp $1 $1 & 0xffff ; mask possible sign bit
SendMessage $0 ${WM_SETTEXT} 0 "STR:$INSTDIR"
SendMessage $0 ${EM_SETSEL} $1 $1
StrCpy $InOnVerifyInstDir 0
${EndIf}
FunctionEnd
but I would still recommend just using InstallDir.

When I am clicking on "Finish" button or close button at the top right corner of the custom page, page is not closing using NSIS

I am facing a weird problem, I have added a new custom page (MyAbruptPage). When clicking on "Finish" button or close button at the top right corner of this custom page, page is not closing.
Scenario:
When Installing the software, if something went wrong and installation hasn't done properly it shows a MessageBox from INSTFILES page. Upon click on "OK" on the message box It is navigating to the "Abrupt" page. In the Abrupt Page it is showing "Finish" button, but when clicked on "Finish" the page is not closing instead it is showing a pop-up message (Are you sure you want to close?). Even when i clicked on close button in the top right corner also i am getting the same pop-up message. I don't want that message and the dialog should be closed when clicked on "Finish" button.
Observations:
I am thinking that the problem is due to the sequence of the pages. Because here i have used two custom pages (MyInfoPage, And MyAbruptPage).
If I replace the first page (MyInfoPage) with MyAbruptPage. Then I am not seeing any issue when clicking on "Finish" button in the Abrupt Page.
Below is my code snippet showing pages and its sequence:
Page Custom MyInfoPage ; First Custom page
!define MUI_PAGE_CUSTOMFUNCTION_SHOW WelShow
!insertmacro MUI_PAGE_WELCOME
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyLicenseShowCallback
!insertmacro MUI_PAGE_LICENSE
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyDirectoryShowCallback
!insertmacro MUI_PAGE_DIRECTORY
Page Custom MyAbruptPage ; Second Custom Page
!define MUI_PAGE_CUSTOMFUNCTION_SHOW AbruptShow
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE AbruptLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
; Below is my code for the Abrupt page
Function AbruptShow
StrCpy $IsOnAbruptPage 1
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
FunctionEnd
Function AbruptLeave
StrCpy $IsOnAbruptPage 0
FunctionEnd
Function MyAbruptPage
${IfThen} $IsOnAbruptPage == "" ${|} Abort ${|}
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0 ; Hide Next button
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0 ; Hide Back button
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
${NSD_CreateLabel} 120u 10u 195u ${MUI_WELCOMEPAGE_TITLE_HEIGHT}u "$(AbruptTitle)"
Pop $AbruptPageTitle
;SetCtlColors $InterruptPageTitle "" "${MUI_BGCOLOR}"
CreateFont $AbruptPageFont "$(^Font)" "12" "700"
SendMessage $AbruptPageTitle ${WM_SETFONT} $AbruptPageFont 0
${NSD_CreateLabel} 120u ${MUI_WELCOMEPAGE_TEXT_TOP}u 195u 130u "$(AbruptText)"
Pop $AbruptPageText
Pop $0
nsDialogs::Show
${NSD_FreeImage} $ImageHandle
FunctionEnd
Below is the section and from here Message box is popping up and navigating to the Abrupt screen:
;!insertmacro MUI_LANGUAGE "English"
Section MySection
SetOutPath $INSTDIR
MessageBox MB_OK|MB_ICONEXCLAMATION "Installation hasn't done properly" IDOK
Call AbruptLeave
SendMessage $HWNDPARENT 0x408 -1 ""
Abort
SectionEnd
;Below is the code for the custompage "MyInfoPage"
Function MyInfoPage
${IfThen} $PageId == "" ${|} Abort ${|}
StrCpy $PageId 0
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0 ; Hide Next button
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
${NSD_CreateLabel} 120u 10u 195u ${MUI_WELCOMEPAGE_TITLE_HEIGHT}u "$(InterruptTitle)"
Pop $InterruptPageTitle
${NSD_CreateLabel} 120u ${MUI_WELCOMEPAGE_TEXT_TOP}u 195u 130u "$(InterruptText)"
Pop $InterruptPageText
nsDialogs::Show
${NSD_FreeImage} $ImageHandle
FunctionEnd
Function WelShow
StrCpy $PageId 1
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0 ; Hide Back button
FunctionEnd
Function onAbort
${If} $PageId <> 0
${If} ${Cmd} ` MessageBox MB_YESNO "Are you sure you want to close?" IDYES `
SendMessage $HWNDPARENT 0x408 -$PageId ""
${EndIf}
Abort
${EndIf}
FunctionEnd
I have tried by changing the sequence of the pages and every time I am observing different behaviors in both the custom pages. Please help me how to resolve this issue? And the correct way to implement this functionality.
Thank you in advance...
Below is the complete code and it is compiling:
Var PageId
Var PrintBtn
Var Image
Var ImageHandle
Var MyInfoPageTitle
Var MyInfoPageFont
var MyInfoPageText
var IsOnAbruptPage
Var AbruptPageTitle
Var AbruptPageFont
var AbruptPageText
!define MUI_CUSTOMFUNCTION_ABORT onAbort
!include "MUI2.nsh"
!include x64.nsh
Name "MyApp"
OutFile "MyApp.exe"
InstallDir "$PROGRAMFILES32\MyApp"
InstallDirRegKey HKLM "Software\MyApp" "Install_Dir"
RequestExecutionLevel admin
!include LogicLib.nsh
;--------------------------------
Page Custom MyInfoPage
!define MUI_PAGE_CUSTOMFUNCTION_SHOW WelShow
!define MUI_TEXT_WELCOME_INFO_TITLE $(welcometitle)
!define MUI_TEXT_WELCOME_INFO_TEXT $(welcometext)
!insertmacro MUI_PAGE_WELCOME
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyLicenseShowCallback
!define MUI_LICENSEPAGE_CHECKBOX ""
!define MUI_INNERTEXT_LICENSE_BOTTOM ""
!define MUI_INNERTEXT_LICENSE_TOP ""
!define MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX ""
!define MUI_TEXT_LICENSE_TITLE $(licensetitle)
!define MUI_TEXT_LICENSE_SUBTITLE $(licensesubtitle)
!define MUI_LICENSEPAGE_CHECKBOX_TEXT $(licensecheckboxtext)
!insertmacro MUI_PAGE_LICENSE "C:\Program Files (x86)\NSIS\Docs\Modern UI 2\license.txt"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyDirectoryShowCallback
!define MUI_DIRECTORYPAGE_TEXT_TOP $(mydirtoptext)
!define MUI_TEXT_DIRECTORY_TITLE $(mydirtitle)
!define MUI_TEXT_DIRECTORY_SUBTITLE $(mydirsubtitle)
!insertmacro MUI_PAGE_DIRECTORY
Page Custom MyAbruptPage
!define MUI_PAGE_CUSTOMFUNCTION_SHOW AbruptShow
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE AbruptLeave
!insertmacro MUI_PAGE_INSTFILES
!define MUI_TEXT_FINISH_INFO_TITLE $(Finishpagetitle)
!define MUI_TEXT_FINISH_INFO_TEXT $(Finishpagesubtitle)
!define MUI_FINISHPAGE_RUN ""
!define MUI_FINISHPAGE_RUN_TEXT $(FinishonlineReg)
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
!insertmacro MUI_LANGUAGE "English"
Function .onInit
InitPluginsDir
FunctionEnd
Function MyDirectoryShowCallback
StrCpy $PageId 3
GetDlgItem $0 $hwndparent 1 ;
SendMessage $0 ${WM_SETTEXT} 0 `STR:$(^NextBtn)`
FunctionEnd
Function MyLicenseShowCallback
StrCpy $PageId 2
GetDlgItem $0 $hwndparent 2
System::Call *(i,i,i,i)p.r1
System::Call 'USER32::GetWindowRect(pr0,pr1)'
System::Call *$1(i.r2,i.r3,i.r4,i.r5)
IntOp $5 $5 - $3 ;height
IntOp $4 $4 - $2 ;width
System::Call 'USER32::ScreenToClient(p$hwndparent,pr1)'
System::Call *$1(i.r2,i.r3)
System::Free $1
IntOp $2 $4 / 5
System::Call 'USER32::CreateWindowEx(i 0,t "Button",t "Print",i ${WS_CHILD}|${WS_VISIBLE}|${WS_TABSTOP},i r2,i r3,i r4,i r5,p $hwndparent,p 0x666,p 0,p 0)p.r0'
StrCpy $PrintBtn $0
SendMessage $hwndparent ${WM_GETFONT} 0 0 $1
SendMessage $0 ${WM_SETFONT} $1 1
ButtonEvent::AddEventHandler 0x666 $0
FunctionEnd
Function WelShow
StrCpy $PageId 1
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
FunctionEnd
Function MyInfoPage
${IfThen} $PageId == "" ${|} Abort ${|}
StrCpy $PageId 0
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
!define MUI_WELCOMEPAGE_TITLE_HEIGHT 38
!define /math MUI_WELCOMEPAGE_TEXT_TOP 17 + ${MUI_WELCOMEPAGE_TITLE_HEIGHT}
${NSD_CreateLabel} 120u 10u 195u 28u "Setup Wizard was interrupted"
Pop $MyInfoPageTitle
CreateFont $MyInfoPageFont "$(^Font)" "12" "700"
SendMessage $MyInfoPageTitle ${WM_SETFONT} $MyInfoPageFont 0
${NSD_CreateLabel} 120u ${MUI_WELCOMEPAGE_TEXT_TOP}u 195u 130u "Setup Wizard was interrupted"
Pop $MyInfoPageText
Pop $0
nsDialogs::Show
${NSD_FreeImage} $ImageHandle
FunctionEnd
Function onAbort
${If} $PageId <> 0
${If} ${Cmd} ` MessageBox MB_YESNO "Are you sure you want to CANCEL" IDYES `
SendMessage $HWNDPARENT 0x408 -$PageId ""
${EndIf}
Abort
${EndIf}
FunctionEnd
Function AbruptShow
StrCpy $IsOnAbruptPage 1
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
FunctionEnd
Function AbruptLeave
StrCpy $IsOnAbruptPage 0
FunctionEnd
Function MyAbruptPage
${IfThen} $IsOnAbruptPage == "" ${|} Abort ${|}
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
${NSD_CreateLabel} 120u 10u 195u ${MUI_WELCOMEPAGE_TITLE_HEIGHT}u "Setup Wizard ended prematurely"
Pop $AbruptPageTitle
CreateFont $AbruptPageFont "$(^Font)" "12" "700"
SendMessage $AbruptPageTitle ${WM_SETFONT} $AbruptPageFont 0
${NSD_CreateLabel} 120u ${MUI_WELCOMEPAGE_TEXT_TOP}u 195u 130u "Setup Wizard ended prematurely"
Pop $AbruptPageText
Pop $0
nsDialogs::Show
${NSD_FreeImage} $ImageHandle
FunctionEnd
SectionIn RO
SetOutPath $INSTDIR
MessageBox MB_OK|MB_ICONEXCLAMATION "There is an installation failure. Aborting the installation process" IDOK
Call AbruptLeave
SendMessage $HWNDPARENT 0x408 -1 ""
Abort
SectionEnd
Section "Uninstall"
SectionEnd
The MessageBox you see is coming from your own code in your onAbort function!
The fact that you are doing
!define MUI_PAGE_CUSTOMFUNCTION_SHOW AbruptShow
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE AbruptLeave
shows that you have don't understand how custom pages work.
To make your special abort page quit without further action you simple have to do nothing in your onAbort function when you are on that page:
Var PageId
var IsOnAbruptPage
!define MUI_CUSTOMFUNCTION_ABORT onAbort
!include "MUI2.nsh"
!include LogicLib.nsh
Name "MyApp"
#OutFile "MyApp.exe"
InstallDir "$temp\MyApp"
#RequestExecutionLevel admin
OutFile Test.exe
RequestExecutionLevel user
;--------------------------------
Page Custom MyInfoPage
!define MUI_PAGE_CUSTOMFUNCTION_SHOW WelShow
!insertmacro MUI_PAGE_WELCOME
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyLicenseShowCallback
!insertmacro MUI_PAGE_LICENSE "${__FILE__}"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyDirectoryShowCallback
!insertmacro MUI_PAGE_DIRECTORY
Page Custom MyAbruptPage
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
;--------------------------------
!insertmacro MUI_LANGUAGE "English"
Function MyDirectoryShowCallback
StrCpy $PageId 3
GetDlgItem $0 $hwndparent 1 ;
SendMessage $0 ${WM_SETTEXT} 0 `STR:$(^NextBtn)`
FunctionEnd
Function MyLicenseShowCallback
StrCpy $PageId 2
FunctionEnd
Function WelShow
StrCpy $PageId 1
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
FunctionEnd
Function MyInfoPage
${IfThen} $PageId == "" ${|} Abort ${|}
StrCpy $PageId 0
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
${NSD_CreateLabel} 120u 10u 195u 28u "Setup Wizard was interrupted"
Pop $0
nsDialogs::Show
FunctionEnd
Function onAbort
${If} $IsOnAbruptPage <> 0 ; If on aborted page
Return ; allow simple exit
${EndIf}
${If} $PageId <> 0
${If} ${Cmd} ` MessageBox MB_YESNO "Are you sure you want to CANCEL" IDYES `
SendMessage $HWNDPARENT 0x408 -$PageId ""
${EndIf}
Abort
${EndIf}
FunctionEnd
Function GoToAbruptPage
StrCpy $IsOnAbruptPage 1
SendMessage $HWNDPARENT 0x408 -1 ""
Abort
FunctionEnd
Function MyAbruptPage
${IfThen} $IsOnAbruptPage == "" ${|} Abort ${|}
GetDlgItem $0 $HWNDPARENT 1
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 0
GetDlgItem $0 $HWNDPARENT 2
${NSD_SetText} $0 "Finish"
nsDialogs::Create 1044
Pop $0
${NSD_CreateLabel} 120u 10u 195u 20u "Setup Wizard ended prematurely"
Pop $0
${NSD_CreateLabel} 120u 120u 195u 20u "Setup Wizard ended prematurely"
Pop $0
nsDialogs::Show
FunctionEnd
;--------------------------------
Section "$(^Name) (required)"
SectionIn RO
SetOutPath $INSTDIR
MessageBox MB_OK|MB_ICONEXCLAMATION "There is an installation failure. Aborting the installation process" IDOK
Call GoToAbruptPage
SectionEnd

How to retain data on custom page when back/next button clicked when the data is taken from a file?

I have written a custom component page which is having a rich text box and that text box shows the information which is read from the "component.rtf" file. When I go first time on my custom page it shows me rich text box filled with data, but when I click next or back button and come back to custom page again at that time it shows me the rich text box as blank. It shows nothing.
I have written following code for my custom page-
;-------Custom page variables---------
Var Dialog
Var CustomHeaderText
Var CustomSubText
Var path
Var temp1
Var CONTROL
;-------------------------------------
Page custom nsDialogsPage
;------Custom page function----------
Function nsDialogsPage
StrCpy $CustomHeaderText "Components of My Installer"
StrCpy $CustomSubText "Detail list of components are"
!insertmacro MUI_HEADER_TEXT $CustomHeaderText $CustomSubText
!define SF_RTF 2
!define EM_STREAMIN 1097
nsDialogs::Create /NOUNLOAD 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
nsDialogs::CreateControl /NOUNLOAD "RichEdit20A" ${ES_READONLY}|${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 0 10u 100% 110u ''
Pop $CONTROL
FileOpen $4 "$path\components.rtf" r
StrCpy $0 $CONTROL
SendMessage $CONTROL ${EM_EXLIMITTEXT} 0 0x7fffffff
; set EM_AUTOURLDETECT to detect URL automatically
SendMessage $CONTROL 1115 1 0
System::Get /NoUnload "(i, i .R0, i .R1, i .R2) iss"
Pop $2
System::Call /NoUnload "*(i 0, i 0, k r2) i .r3"
System::Call /NoUnload "user32::SendMessage(i r0, i ${EM_STREAMIN}, i ${SF_RTF}, i r3) i.s"
loop:
Pop $0
StrCmp $0 "callback1" 0 done
System::Call /NoUnload "kernel32::ReadFile(i $4, i $R0, i $R1, i $R2, i 0)"
Push 0 # callback's return value
System::Call /NoUnload "$2"
goto loop
done:
System::Free $2
System::Free $3
FileClose $4
nsDialogs::Show
FunctionEnd
;--------Custom page function end------------
In above code it reads the file "components.rtf" and displays it. Can someone tell me how to write the code which will retain this data when I will click Back/Next button on component page.?
It works fine for me. Perhaps you are overwriting $path on another page? Add MessageBox MB_OK $4 after FileOpen to make sure you are able to open the file.
!include MUI2.nsh
Var Dialog
Var CustomHeaderText
Var CustomSubText
Var path
#Var temp1
Var CONTROL
;-------------------------------------
Page custom nsDialogsPage
;------Custom page function----------
Function nsDialogsPage
StrCpy $CustomHeaderText "Components of My Installer"
StrCpy $CustomSubText "Detail list of components are"
!insertmacro MUI_HEADER_TEXT $CustomHeaderText $CustomSubText
!define SF_RTF 2
!define EM_STREAMIN 1097
nsDialogs::Create /NOUNLOAD 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
nsDialogs::CreateControl /NOUNLOAD "RichEdit20A" ${ES_READONLY}|${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 0 10u 100% 110u ''
Pop $CONTROL
FileOpen $4 "$path\components.rtf" r
StrCpy $0 $CONTROL
SendMessage $CONTROL ${EM_EXLIMITTEXT} 0 0x7fffffff
; set EM_AUTOURLDETECT to detect URL automatically
SendMessage $CONTROL 1115 1 0
System::Get /NoUnload "(i, i .R0, i .R1, i .R2) iss"
Pop $2
System::Call /NoUnload "*(i 0, i 0, k r2) i .r3"
System::Call /NoUnload "user32::SendMessage(i r0, i ${EM_STREAMIN}, i ${SF_RTF}, i r3) i.s"
loop:
Pop $0
StrCmp $0 "callback1" 0 done
System::Call /NoUnload "kernel32::ReadFile(i $4, i $R0, i $R1, i $R2, i 0)"
Push 0 # callback's return value
System::Call /NoUnload "$2"
goto loop
done:
System::Free $2
System::Free $3
FileClose $4
nsDialogs::Show
FunctionEnd
Function .onInit
; Create a RTF file
InitPluginsDir
StrCpy $path "$PluginsDir" ; Set $path used by the custom page
FileOpen $0 "$path\components.rtf" w
FileWrite $0 '{\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard{Show {\b Me}}\par{http://example.com/#Funny}\par{Goodbye}}'
FileClose $0
FunctionEnd
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
Section
SectionEnd

Resources