Archive: Delay when displaying a custom page


Delay when displaying a custom page
I have a relatively simple NSIS script that has a custom page that is displayed if a user selects a specific section option. When I run the installer, if the user does not select this "special" option everything runs as normal. However if the "special" section is selected, when the user clicks next the header text and button of the installer form immediately change (to that of the custom page) and about 4 or 5 seconds later the main body of the custom page is displayed??!?

This custom page only contains 2 labels, a group box and a file browse box, so it shouldnt take long to read, parse and display the contents of the ini file. So does anybody have any ideas as to the cause of the delay?

If it helps at all, these are the relevant parts of the script:

Page ordering

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${PATH_TO_FILES}\License.txt"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
Page custom GetCustomScriptPath
!insertmacro MUI_PAGE_INSTFILES


Name of INI file is defined at the top of the script as follows:

!DEFINE NSIS_CUSTOM_SCRIPT_INI "CustomScriptSelection.ini"


The code for my custom page is as follows (I have highlighted the line where the pause seems to occur)


Function GetCustomScriptPath
SectionGetFlags ${is_CustomScript} $R0
IntOp $R0 $R0 & ${SF_SELECTED}
IntCmp $R0 ${SF_SELECTED} show
Abort

;;show the custom page
show:
!insertmacro MUI_INSTALLOPTIONS_EXTRACT ${NSIS_CUSTOM_SCRIPT_INI}
!insertmacro MUI_HEADER_TEXT "Custom script selection" "Enter the full path and file name of your custom installation script."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY ${NSIS_CUSTOM_SCRIPT_INI}

;;Get the entered values into vars
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_SCRIPT_PATH ${NSIS_CUSTOM_SCRIPT_INI} "Field 2" "State"
FunctionEnd


As you can see if the "is_CustomScript" section is not selected this section simply quits, if it is selected then the custom page code is executed

Interestingly if I add a 'MessageBox MB_OK "boo!"' just above the highlighted line the delay rarely occurs. As soon as I click "ok" on the message box the custom page is displayed

The following is the contents of my custom page ini file


[Settings]
NumFields=4

[Field 1]
Type=Groupbox
Text=Enter custom script path and file name
Left=0
Right=300
Top=44
Bottom=89

[Field 2]
Type=FileRequest
Text=C:\
State=C:\
Left=5
Right=290
Top=61
Bottom=74

[Field 3]
Type=Label
Text=You have selected to use a custom installation script to configure your XXXX System, please use the dialog below to select the custom script to use.
Flags=NOTABSTOP
Left=0
Right=300
Top=4
Bottom=35

[Field 4]
Type=Label
Text=Refer to documentation for further information regarding custom installation scripts.
Flags=NOTABSTOP
Left=0
Right=300
Top=98
Bottom=126

You should extract the INI file in .onInit or reserve it so it's at the top of the data block using ReserveFile. So, either use MUI_INSTALLOPTIONS_EXTRACT in .onInit, or use `ReserveFile ${NSIS_CUSTOM_SCRIPT_INI}` at the top of the script.


Before posting I spent some time hunting around the docs and wiki and came across these suggestions, however I couldnt seem to get them to work.

As examples I added the following to .onInit

!insertmacro MUI_INSTALLOPTIONS_EXTRACT ${NSIS_CUSTOM_SCRIPT_INI}


Which seems to randomly fix the problem, i.e. 10% of installer executions worked fine, the other 90% still had a delay.

I also tried adding:

ReserveFile ${NSIS_CUSTOM_SCRIPT_INI}


Just under where I defined the value, however this didnt seem to make any difference at all.

Also tried a combination of both of these ideas, also with no perceivable improvement

As a long shot I also tried the following in the .onInit

InitPluginsDir
SetOutPath $PLUGINSDIR
File /oname=$PLUGINSDIR\${NSIS_CUSTOM_SCRIPT_INI} ${NSIS_CUSTOM_SCRIPT_INI}


With and without combination of the other ideas, all to no avail

Out of context, I can't tell if those were placed in the correct places. .onInit has to be at the top of the script as well, I forgot to mention that.


Originally posted by kichik
....onInit has to be at the top of the script as well, I forgot to mention that....
My .onInit was after the sections, I have moved it and that seems to work with the call to MUI_INSTALLOPTIONS_EXTRACT

However this has created another issue, the reason the function was after the sections is that I have the following in onInit


StrCpy $1 ${is_DefaultScript}


which inturn uses

Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${is_DefaultScript}
!insertmacro RadioButton ${is_SingleSiteScript}
!insertmacro RadioButton ${is_CustomScript}
!insertmacro RadioButton ${is_NoneScript}
!insertmacro EndRadioButtons
FunctionEnd


This "is_DefaultScript" is an install section that forms part of a group of section that act as radio selection, and this section is the default selection. If I move the onInit I get the following compiler warning

1 warning:
unknown variable/constant "{is_DefaultScript}" detected, ignoring
And my radios no longer work

Then use ReserveFile at that location, it's effectively the same.


I seem to have lost the plot on this one, for some reason what we discussed seems to have stopped working and I am back to a delay again :igor:

As you mentioned, these types of things are difficult to accurately diagnose when out of context, so here is the script I am working with. Hopefully somebody will be able to point out my rather silly mistake.


#################################################################
# Includes
#################################################################
!include "Sections.nsh"
!include "MUI.nsh"

#################################################################
# Script constants
#################################################################
!DEFINE PATH_TO_FILES "OutputData";
!DEFINE DEFAULT_INSTALL_DIR "C:\WidgetApp"
!DEFINE NSIS_CUSTOM_SCRIPT_INI "WidgetApp_ScriptSelection.ini"

#################################################################
# General script vars
#################################################################
Var INSTALL_SCRIPT_PATH "${DEFAULT_INSTALL_DIR}\Bin\InstallData\InstallScript_Default.bat"

#################################################################
# Init Functions
#################################################################
;ReserveFile ${NSIS_CUSTOM_SCRIPT_INI} ;reserve custom page ini file to prevent pauses when displayed

Function .onInit
;extract the custom page ini file to prevent delays if the page is displayed
;this doubles up with the ReserveFile call
!insertmacro MUI_INSTALLOPTIONS_EXTRACT ${NSIS_CUSTOM_SCRIPT_INI}
FunctionEnd

#################################################################
# Check command line parameters passed
#################################################################
!ifdef ${VSBUILD}
!ifndef ${VERSION}
!error "SCRIPT CANNOT COMPILE WITHOUT VERSION PARAMETER - USE /DVERSION=xxxx ON COMMAND LINE"
!endif

!ifndef ${REVISION}
!error "SCRIPT CANNOT COMPILE WITHOUT REVISION PARAMETER - USE /DREVISION=xxxx ON COMMAND LINE"
!endif
!endif

!ifndef ${VSBUILD}
!DEFINE VERSION "0.0.0.0"
!DEFINE REVISION "000"
!endif

#################################################################
# General script params
#################################################################
CRCCheck on
XPStyle on
LicenseForceSelection radiobuttons
BGGradient 007ac1 FFFFFF
BrandingText "© Widgets PLC"
Name "Amazing Widget App" ;name
OutFile "WidgetApp_${VERSION}_r${REVISION}.exe" ;output file
InstallDir ${DEFAULT_INSTALL_DIR}
Caption "Widget Application ${VERSION} r${REVISION} Setup" ;installer form caption
ShowInstDetails show
ShowUninstDetails show

#################################################################
# Configure Interface (Based on NSIS MUI Interface)
#################################################################
;base settings
!define MUI_CUSTOMFUNCTION_GUIINIT scriptGuiInit ;additional init to handle selection on script radios
!define MUI_ICON icon.ico
!define MUI_UNICON icon.ico
!define MUI_ABORTWARNING

;gui images
!define MUI_COMPONENTSPAGE_SMALLDESC

;page settings
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_NOREBOOTSUPPORT

;page texts
!define MUI_WELCOMEPAGE_TITLE "Welcome to the Widget App."
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Widget Application ${VERSION}, the next generation of the Windows installer and uninstaller system that doesn't suck and isn't huge.\r\n\r\nNSIS 2 includes a new Modern User Interface, LZMA compression, support for multiple languages and an easy plug-in system.\r\n\r\n$_CLICK"
!define MUI_FINISHPAGE_LINK "Visit the Widget App home page."
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.widgetapp.com.com/"

;install page order
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "WidgetApp_License.txt"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
Page custom GetCustomScriptPath
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

;uninstall page order
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

;language options
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_RESERVEFILE_LANGDLL

#################################################################
# Set installer executable version info
#################################################################
VIProductVersion "${VERSION}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Widget App"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "Refer to documentation."
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Widgets PLC"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" "Widget App is a trademark of Widgets PLC"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "© Widgets PLC"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "Widget App System Installer"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION} r${REVISION}"

#################################################################
# Install Sections
#################################################################
;checks the target system to ensure that pre requistes exist
;IIS, .NET Framework
Section "Verify Prerequisites" is_VerfiyPrereqs
SectionEnd

Section "!Install Base Files" is_BaseFiles
;install files
SetOutPath $INSTDIR
File /r /x _svn /x .svn ${PATH_TO_FILES}\*.*
SectionEnd

SectionGroup /e "Installation Script"
Section "Default" is_DefaultScript
StrCpy $INSTALL_SCRIPT_PATH "$INSTDIR\bin\InstallData\InstallScript_Default.bat"
Call ExecuteInstallScript
SectionEnd

Section /o "Single Site" is_SingleSiteScript
StrCpy $INSTALL_SCRIPT_PATH "$INSTDIR\bin\InstallData\InstallScript_SingleSite.bat"
Call ExecuteInstallScript
SectionEnd

Section /o "Custom" is_CustomScript
Call ExecuteInstallScript
SectionEnd

Section /o "None" is_NoneScript
SectionEnd
SectionGroupEnd

Section -Hidden_Finish
WriteUninstaller $INSTDIR\uninstall.exe
SectionEnd

#################################################################
# Install Functions
#################################################################
Function GetCustomScriptPath
SectionGetFlags ${is_CustomScript} $R0
IntOp $R0 $R0 & ${SF_SELECTED}
IntCmp $R0 ${SF_SELECTED} show
Abort

;;show the custom page
show:
!insertmacro MUI_INSTALLOPTIONS_EXTRACT ${NSIS_CUSTOM_SCRIPT_INI}
!insertmacro MUI_HEADER_TEXT "Custom script selection" "Enter the full path and file name of your custom installation script."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY ${NSIS_CUSTOM_SCRIPT_INI}

;;Get the entered values into vars
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_SCRIPT_PATH ${NSIS_CUSTOM_SCRIPT_INI} "Field 2" "State"
FunctionEnd

Function ExecuteInstallScript
DetailPrint "Executing installation script."
MessageBox MB_OK "nsExec::ExecToLog '$INSTALL_SCRIPT_PATH'"
FunctionEnd

#################################################################
# Uninstall sections
#################################################################
Section Uninstall
SectionEnd

#################################################################
# Installer Section Description
#################################################################
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN

!insertmacro MUI_DESCRIPTION_TEXT ${is_VerfiyPrereqs} "Verify that prequistes are available."
!insertmacro MUI_DESCRIPTION_TEXT ${is_BaseFiles} "Installs all required files to chosen directory."
!insertmacro MUI_DESCRIPTION_TEXT ${is_DefaultScript} "Uses the default installation script."
!insertmacro MUI_DESCRIPTION_TEXT ${is_SingleSiteScript} "Uses the default single site installation script."
!insertmacro MUI_DESCRIPTION_TEXT ${is_CustomScript} "Use custom script for installation, you will be prompted for the script location."
!insertmacro MUI_DESCRIPTION_TEXT ${is_NoneScript} "Does not execute any post install script."
!insertmacro MUI_FUNCTION_DESCRIPTION_END

#################################################################
# Misc Internal Script Functions
#################################################################
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${is_DefaultScript}
!insertmacro RadioButton ${is_SingleSiteScript}
!insertmacro RadioButton ${is_CustomScript}
!insertmacro RadioButton ${is_NoneScript}
!insertmacro EndRadioButtons
FunctionEnd

function scriptGuiInit
;set default script selection
StrCpy $1 ${is_DefaultScript}
FunctionEnd


For the sake of some clarity I have removed alot of other functionality from this script - however after compile it still has the delay

You've the right code in the right place in both cases. However, you didn't reserve the InstallOptions plug-in itself as instructed in the MUI readme. Use the following:

!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
See section 6 in the MUI readme for more information.

Please attach scripts next time. It makes the thread harder to read with lots of inlined code.

Apologies for the inline script, I stand suitably chastised (I would edit, however forum configuration doesnt allow it)

I seem to have found a final solution to this, and as hinted at in earlier posts this was due to a bug in the human brain (ID-10T error apparently)

After much fiddling with ReserveFile, MUI_RESERVEFILE_INSTALLOPTIONS and MUI_INSTALLOPTIONS_EXTRACT I was getting nowhere fast. Then in a blinding moment of lucidity I realised where I had gone wrong:

My custom page function (GetCustomScriptPath) included the following lines:

!insertmacro MUI_INSTALLOPTIONS_EXTRACT "WidgetApp_ScriptSelection.ini"
!insertmacro MUI_HEADER_TEXT "Header Text" "Some Header Text Goes Here."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "WidgetApp_ScriptSelection.ini"
!insertmacro MUI_INSTALLOPTIONS_READ $R0 "WidgetApp_ScriptSelection.ini" "Field 2" "State"


The problem was that the custom page function was re-extracting the install options files even though it had been reserved earlier. If this line is commented out, everything works like a dream.

MUI_INSTALLOPTIONS_READ will not work if used in there. You must use it in the Leave function.

-Stu