Archive: Custom Page :: Next button


Custom Page :: Next button
  I have made additional custom page with button "uninstall" , this page appears
if product is already installed. I also try to keep button "next" disabled
until user uninstall previous version.
I disabled it sucessfully but i can't turn it enabled back.

What's wrong with this code?


product.ini
---------------------------

[Settings]
NumFields=2

[Field 1]
Type=label
Text=uninstall need
Left=0
Right=-1
Top=0
Bottom=10

[Field 2]
Type=Button
Flags=NOTIFY
Text=&Uninstall..
Left=-60
Right=-10
Top=19
Bottom=33


install_product.nsi
---------------------------

!define PRODUCT_NAME "product"
!define PRODUCT_FILEVERSION "10"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_PUBLISHER "me"
!define PRODUCT_WEB_SITE ""
!define PRODUCT_UNINSTALLER "uninstall.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "product:StartMenuDir"


!include "MUI.nsh"


Page custom PageAlreadyInstalled PageAlreadyInstalledLeave

!insertmacro MUI_PAGE_DIRECTORY


; Start menu page
var ICONS_GROUP
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "product"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP

!insertmacro MUI_PAGE_INSTFILES

!insertmacro MUI_LANGUAGE "English"

ReserveFile "product.ini"
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS


Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "install_product${PRODUCT_FILEVERSION}.exe"
InstallDir "$PROGRAMFILES\product"

LangString messNotPlugins ${LANG_RUSSIAN} "Âûáðàííûé êàòàëîã íå ÿâëÿåòñÿ êàòàëîãîì ïëàãèíîâ Far ïî óìîë÷àíèþ. Ïðîäîëæèòü?"
;LangString messNotPlugins ${LANG_ENGLISH} "Selected folder is not default folder for Far plugins. Continue?"



;LangString TEXT_IO_TITLE ${LANG_ENGLISH} "InstallOptions page"
;LangString TEXT_IO_SUBTITLE ${LANG_ENGLISH} "This is a page created using the InstallOptions plug-in."
LangString TEXT_IO_TITLE ${LANG_ENGLISH} "Îáíàðóæåíà ïðåäûäóùàÿ èíñòàëÿöèÿ"
LangString TEXT_IO_SUBTITLE ${LANG_RUSSIAN} "Íà êîìïüþòåðå óæå óñòàíîâëåíà product"


Function .onInit
InitPluginsDir
File /oname=$PLUGINSDIR\product.ini product.ini
FunctionEnd

Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SectionEnd

Section -Post
WriteUninstaller "$INSTDIR\${PRODUCT_UNINSTALLER}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\${PRODUCT_UNINSTALLER}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_UNINSTALLER},0"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "${PRODUCT_STARTMENU_REGVAL}" "$ICONS_GROUP"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "NoModify" "1"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "NoRepair" "1"
SectionEnd


Function un.onInit
FunctionEnd

Section Uninstall
ReadRegStr $ICONS_GROUP ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "${PRODUCT_STARTMENU_REGVAL}"

; Delete self
Delete "$INSTDIR\${PRODUCT_UNINSTALLER}"
RMDir /r "$INSTDIR"
RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
SetAutoClose false
SectionEnd




Function CheckAlreadyInstalled
ReadRegStr $R0 "${PRODUCT_UNINST_ROOT_KEY}" "${PRODUCT_UNINST_KEY}" "UninstallString"
FunctionEnd

Function PageAlreadyInstalled
call CheckAlreadyInstalled
StrCmp $R0 "" 0 +2
Abort

ifFileExists $R0 showPage WasManuallyDeleted
WasManuallyDeleted:
Abort

showPage:

GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 0

!insertmacro MUI_HEADER_TEXT "$(TEXT_IO_TITLE)" "$(TEXT_IO_SUBTITLE)"

loop:
!insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "product.ini"
pop $0
messagebox mb_ok $0
strCmp $0 "success" 0 end0
call CheckAlreadyInstalled
StrCmp $R0 "" 0 loop
end0:
FunctionEnd


Function PageAlreadyInstalledLeave
ReadINIStr $0 "$PLUGINSDIR\product.ini" "Settings" "State"

StrCmp $0 0 done ; Next button?
StrCmp $0 2 btnUninstall
Abort

btnUninstall:
GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 1
ClearErrors
ExecWait '$R0 _?=$INSTDIR'
abort
done:
call CheckAlreadyInstalled
StrCmp $R0 "" next1
Abort
next1:
FunctionEnd


Add a messagebox to check whether it gets to your EnableWindow call and check whether the control handle is correct.


I spend 3 hours checking handles, they are okey. "Next" button gets enabled, but after uninstaller finshes, It turns back to disabled. Seems to me, nsis did that. I am sure my script doesnt disable it second time.


Can you please explain exactly what goes wrong? After the installation has finished, NSIS will disable the Next button.


this is picture just before the uninstall have finished.

When back window was show up, button 2 was disabled by my code.
When user launched uninstall, button 2 was enabled by my code.

So, now it is enabled.
but,if i click button 1 now, the button 2 will sudenly got disabled, and this is wrong.


This is exactly the same button. Cancel is always disabled when the uninstallation has finished.


So why this code does not enable the button ?
btnUninstall:
ClearErrors
ExecWait '$R0 _?=$INSTDIR'

GetDlgItem $R4 $HWNDPARENT 1
messageBox mb_ok "Here, $R4"
EnableWindow $R4 1

abort


So you mean that the button is disabled after you close the uninstaller? The uninstaller has nothing to do with the installer.

When exactly does it enable the button? Does it wait for the installer?

Add some messageboxes before every step in your leave function.


YES. installer's button "Next" gets disabled after i call Abort in leave function. Please compile code i provide in first message, it compiles with no problem. I am attaching source and compiled exe


Add a messagebox before the other EnableWindow call, is that one called again?


No, EnableWindow is not called again. No code executed after Abort call.


So the first EnableWindows call (with the 0 parameter) is not called?

Do you get the same behavior if you do not run the uninstaller?


Yes, it is not called again. things are same if installer does not run at all.
This is minimal code that reproduce this bahavoir.
Function PageEnter
GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 0
sleep 500
messageBox mb_OK "disabled $R4"
!insertmacro MUI_HEADER_TEXT "$(TEXT_IO_TITLE)" "$(TEXT_IO_SUBTITLE)"
loop:
!insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "product.ini"
pop $0
goto loop
FunctionEnd

Function PageLeave
GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 1
sleep 500
MessageBox mb_ok "enabled $R4"
Abort
FunctionEnd


Another minimal example. Do anybody hear me?


PageEnter

GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 0
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "product.ini"
>FunctionEnd

>Function PageLeave
GetDlgItem $R4 $HWNDPARENT 1
EnableWindow $R4 1
Abort
FunctionEnd
>

It seems to restore the button state. For now you can use display a messagebox if uninstall was not clicked.


Ok. For now i'll not use such page at all; unil next nsis release, i'll use messagebox in .onInit. Thank you.


fixed.