Skip to content
⌘ NSIS Forum Archive

INSTDIR vs Component

4 posts

sandal1306#

INSTDIR vs Component

Hi All -

Does anyone know how to have the choice of the installation directory for each component I got in the code?

Is there an easy way to proceed using the standard Page or do I have to create a custom one?
sandal1306#
Adding some precision:

How can I have in a Directory Page several lines corresponding of the install path of the different components selected in the Component Page?
Animaether#
There's at least two simple ways you could do this... both require you to put multiple Directory pages behind the Components page.

The following is assuming you're using the Modern UI. It's a bit untested, but should be fine.

# variables to hold the installation directories
var Component1Dir
var Component2Dir
var Component3Dir
# components page
!insertmacro MUI_PAGE_COMPONENTS
# multiple directory pages
!define MUI_PAGE_CUSTOMFUNCTION_PRE Component1DirPre
!define MUI_DIRECTORYPAGE_VARIABLE Component1Dir
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_PRE Component2DirPre
!define MUI_DIRECTORYPAGE_VARIABLE Component2Dir
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_PRE Component3DirPre
!define MUI_DIRECTORYPAGE_VARIABLE Component3Dir
!insertmacro MUI_PAGE_DIRECTORY
# The file installation 'page'
!insertmacro MUI_PAGE_INSTFILES
# The components (sections)
Section Component1
  # stuff here. Be sure to use the directory variable corresponding
  # to the directory page used. In this case, for example:
  SetOutPath "$Component1Dir"
    File "somefile"
    File "someotherfile"
SectionEnd
Section Component2
  # stuff here
  SetOutPath "$Component2Dir"
    File "somefile"
    File "someotherfile"
SectionEnd
Section Component3
  # stuff here
  SetOutPath "$Component3Dir"
    File "somefile"
    File "someotherfile"
SectionEnd
# Functions run before showing each directory page.
# Here we'll call Abort to stop the page from showing up
#  if the user didn't select the component
Function Component1DirPre
  # Get the flags for the section
  SectionGetFlags ${Component1} $R0
  # Binary 'and' with value '1' (selected or not)
  IntOp $R0 $R0 & 1
  # If it is not selected
  IntCmp $R0 0 0 +2
    # Then Abort. This will prevent the page from showing up
    Abort
  # Otherwise, continue
FunctionEnd
Function Component2DirPre
  SectionGetFlags ${Component2} $R0
  IntOp $R0 $R0 & 1
  IntCmp $R0 0 0 +2
    Abort
FunctionEnd
Function Component3DirPre
  SectionGetFlags ${Component3} $R0
  IntOp $R0 $R0 & 1
  IntCmp $R0 0 0 +2
    Abort
FunctionEnd 
--------------------------------------------------

Another method, where you wouldn't require multiple directory variables, would be to put the actual file installation/operation instructions in the Directory pages' Post functions. This is less desirable for various reasons - mostly the log display won't be right. If you don't care about that, though, it might be easier to work with as all the code corresponding to a particular directory is right there in the directory handling functions.

--------------------------------------------------

Lastly, you could make a custom page with multiple directory fields. This would look cleaner (having a user go through 5 directory pages, for example, would be a bit ick), but also require much more work (think hiding fields if the components aren't selected, still have to store multiple directory variables, etc.)
Animaether#
To specifically answer your second post : yes, you'd have to create a custom page.
I've done one with two directories myself, and it's not impossible, but it's not supersimple either 🙂
The most limiting factor is dialog real-estate. You'd need a bigger dialog if you want a whole bunch of directory fields. That, or put up with a relatively ugly page.