0
votes

I want to validate the installation path selected by the user. I can't figure out how to check that so it will look like this:

  • You can't select a path with spaces (except Program Files)
  • When you click "Install" then it will prompt the error saying that you have to change the installation directory

For now I have this:

  Function StrStr
  Exch $1 ; st=haystack,old$1, $1=needle
  Exch    ; st=old$1,haystack
  Exch $2 ; st=old$1,old$2, $2=haystack
  Push $3
  Push $4
  Push $5
  StrLen $3 $1
  StrCpy $4 0
  ; $1=needle
  ; $2=haystack
  ; $3=len(needle)
  ; $4=cnt
  ; $5=tmp
  loop:
    StrCpy $5 $2 $3 $4
    StrCmp $5 $1 done
    StrCmp $5 "" done
    IntOp $4 $4 + 1
    Goto loop
  done:
  StrCpy $1 $2 "" $4
  Pop $5
  Pop $4
  Pop $3
  Pop $2
  Exch $1
FunctionEnd

Function .onVerifyInstDir
Push "$INSTDIR"
Push " "
Call StrStr
Pop $0
StrCpy $0 $0 1
StrCmp $0 " " 0 +2
  Abort
FunctionEnd

It refuses to install while there is any space in the path. I need to modify this so Program Files will be the only exception for that rule. Also, printing error message would be helpful

1

1 Answers

0
votes

This restriction makes no sense to me. Some legacy applications can't handle spaces in the path but that of course also includes the Program Files folder (although the progra~1 hack can be used as a workaround if short name generation is active).

NSIS does not have a specific way to display a error/warning message directly on the page but you can change existing text in the UI and/or display a balloon.

!include WinMessages.nsh
!define /IfNDef EM_SHOWBALLOONTIP 0x1503
!define /IfNDef EM_HIDEBALLOONTIP 0x1504

!define DIRPAGE_CHANGETEXT ; Remove this line to disable the text change
!define DIRPAGE_BALLOON    ; Remove this line to disable the balloon
Function .onVerifyInstDir
    FindWindow $9 "#32770" "" $HWNDPARENT
!ifdef DIRPAGE_CHANGETEXT
    GetDlgItem $3 $9 1006 ; IDC_INTROTEXT
    LockWindow on
!endif
    StrCpy $1 0
    loop:
        StrCpy $2 $InstDir 1 $1
        StrCmp $2 '' valid ; End of string
        StrCmp $2 ' ' found_space
        IntOp $1 $1 + 1
        Goto loop
valid:
!ifdef DIRPAGE_CHANGETEXT
    SetCtlColors $3 SYSCLR:18 SYSCLR:15
    SendMessage $3 ${WM_SETTEXT} "" "STR:$(^DirText)"
    LockWindow off
!endif
!ifdef DIRPAGE_BALLOON
    GetDlgItem $3 $9 1019
    SendMessage $3 ${EM_HIDEBALLOONTIP} "" "" ; Not required?
!endif
    Return
found_space:
    StrLen $1 "$ProgramFiles\"
    StrCpy $2 "$InstDir\" $1
    StrCmp $2 "$ProgramFiles\" valid
!ifdef DIRPAGE_CHANGETEXT
    SetCtlColors $3 ff0000 transparent
    SendMessage $3 ${WM_SETTEXT} "" "STR:Paths with spaces are not allowed, except for $ProgramFiles for some reason!"
    LockWindow off
!endif
!ifdef DIRPAGE_BALLOON
    GetDlgItem $3 $9 1019
    System::Call '*(&l${NSIS_PTR_SIZE},w "Bad path!", w "Spaced not allowed in path!",p 3)p.r2'
    SendMessage $3 ${EM_SHOWBALLOONTIP} "" $2 ; This will only work on XP and later (and you must use "XPStyle on")
    System::Free $2
!endif
    Abort
FunctionEnd

XPStyle on
Page Directory

The Next button is disabled when Abort is called inside .onVerifyInstDir. If you want to display a MessageBox when the user clicks next then you can't call Abort in .onVerifyInstDir, you will have to use the page leave function callback (where you have to verify the path again and maybe call MessageBox+Abort).