Archive: Creating multiple installers with one script?


Creating multiple installers with one script?
Hello all,

I was curious if it is possible to have a single script that could grab each seperate file from a directory and make a simple installer for each one?

For an example, there is a folder with 600 files inside.
Rather than create 600 seperate scripts for each file,
just have one script that can iterate through each file
and output a corresponding installer.

Has this already been done?

If anyone could point me in the right direction, it would
be most helpful!


What I would do, is create an NSIS installer which reads from your folder of files and writes a temporary NSI script for that file, compiles it, and so on and so forth.

-Stu


Thanks for the quick reply!

I am quite new to NSIS development - if you
could also highlight any particular important
functions I will need to use or a sample
script, that would be v. helpful!

I wouldn't even know where to start with making
temp scripts that could then be sent for
compilation itself!!!


This is a minimal script you can compile. Put the generated exe in the parent folder of the folder that contains all your files, then run it!
Change the !define to the name of your folder first.


OutFile GenerateInstallers.exe

!define FileDir "Files"

Function .onInit
ClearErrors
FindFirst $R0 $R1 "$EXEDIR\${FileDir}\*.*"

# Read file name
Loop:
IfErrors Done
StrCmp $R1 . Next
StrCmp $R1 .. Next

# Get file name w/o ext
StrCpy $R2 $R1 -4

# Write temp script
FileOpen $R3 "$EXEDIR\Installer.nsi" w
FileWrite $R3 'OutFile "$R2.exe"$\r$\n'
FileWrite $R3 'Page Directory$\r$\n'
FileWrite $R3 'Page InstFiles$\r$\n'
FileWrite $R3 'Section$\r$\n'
FileWrite $R3 'File "/oname=$$INSTDIR\$R1" "${FileDir}\$R1"$\r$\n'
FileWrite $R3 'SectionEnd$\r$\n'
FileClose $R3

# Compile temp script
ExecWait '"${NSISDIR}\makensis.exe" "$EXEDIR\Installer.nsi"'

Next:
ClearErrors
FindNext $R0 $R1
Goto Loop

Done:
FindClose $R0

# Delete temp script
Delete "$EXEDIR\Installer.nsi"
Abort
FunctionEnd

Section
SectionEnd


-Stu

Thats great! Thank you - I've modified the script to
what I need but thank you v. much!


Just an extra question to go with this.
If I were to have subfolders inside the
main folder with the files inside, would
anyone be able to direct me to a loop
code that could iterate through each one
of the folders, return back to the parent
folder and continue on with more folders?


I've got a function that just does that which isn't a fixed one (ie I change it to do all sorts of things). This one is closer to home though - it writes the file names it finds to a text file (which is almost what you need!)
You should be able to modify the main parts (ie FileWrite) to what you need.

 Function GetFilesRecursive
Push $R1
Push $R2
Push $R3
Push $R4

StrCpy $R3 1

Push ""

nextDir:
Pop $R4
IntOp $R3 $R3 - 1
ClearErrors

FindFirst $R1 $R2 "$DirPath$R4\*.*"
checkLoop:
IfFileExists "$DirPath$R4\$R2\*.*" +3
FileWrite $R0 '$\r$\n$${SE-OutPath} "$OutputPath$R4"$\r$\n'
Goto checkDone
FindNext $R1 $R2
IfErrors 0 checkLoop
checkDone:
FindClose $R1

FindFirst $R1 $R2 "$DirPath$R4\*.*"

nextFile:
StrCmp $R2 "." gotoNextFile
StrCmp $R2 ".." gotoNextFile

IfFileExists "$DirPath$R4\$R2\*.*" 0 notDir
IntOp $R3 $R3 + 1
Push "$R4\$R2"
Goto gotoNextFile

notDir:
FileWrite $R0 '$${SE-File} "$DirPath$R4\$R2" "$R2"$\r$\n'

gotoNextFile:
FindNext $R1 $R2
IfErrors 0 nextFile

FindClose $R1

StrCmp $R3 0 0 nextDir

Pop $R4
Pop $R3
Pop $R2
Pop $R1
FunctionEnd


Edit: That gives me an idea for a new project. One that works similar to FindFirst, FindNext and FindClose, except that it loops through a folder recursively.

-Stu

Wow !!

That is a really good script!

Definitely not one for the faint-hearted.

I've tried combining the two scripts you have
generously helped with but am currently struggling
to make it work.

I know its cheeky to ask but is it possible you
can help with this step as well?


I think Instructor has made a recursive find function in one of his script headers. I'm not entirely sure and I can't check here at college. You can find such things at the archive (http://nsis.sf.net/archive)

-Stu


Thanks for giving such great help.

Just on the last hurdle now. I've modified
the first script you wrote out but I am
just wanting to integrate some file existence
checking.

I've done the PageEx code in a seperate installer
script so I know that works fine but when trying
to FileWrite the commands into your script, the
final installer exe's for each file do not appear.


OutFile GenerateInstallers.exe

!define FileDir "Database"

Function .onInit
ClearErrors
FindFirst $R0 $R1 "$EXEDIR\${FileDir}\*.*"

# Read file name
Loop:
IfErrors Done
StrCmp $R1 . Next
StrCmp $R1 .. Next

# Get file name w/o ext
StrCpy $R2 $R1 -4

# Write temp script
FileOpen $R3 "$EXEDIR\Installer.nsi" w
FileWrite $R3 'OutFile "$EXEDIR\${FileDir}\$R2.exe"$\r$\n'

FileWrite $R3 'XPStyle on$\r$\n'
FileWrite $R3 'SetFont "Verdana" 8$\r$\n'

FileWrite $R3 'InstallDir "$PROGRAMFILES\test\test"$\r$\n'
FileWrite $R3 'InstallDirRegKey HKLM "Software\test" "Install_Dir"$\r$\n'

FileWrite $R3 'PageEx Directory$\r$\n'
FileWrite $R3 'PageCallbacks "" ""checkFileExistence'
FileWrite $R3 'PageExEnd'

FileWrite $R3 'Page instfiles$\r$\n'

FileWrite $R3 'Function checkFileExistence'
FileWrite $R3 'IfFileExists "$INSTDIR\tester.exe" +3'
FileWrite $R3 'MessageBox MB_OK|MB_ICONEXCLAMATION "Please install the database to a valid folder"'
FileWrite $R3 'Abort'
FileWrite $R3 'FunctionEnd'

FileWrite $R3 'Section$\r$\n'

FileWrite $R3 'File "/oname=$$INSTDIR\${FileDir}\$R1" "${FileDir}\$R1"$\r$\n'
FileWrite $R3 'SectionEnd$\r$\n'
FileClose $R3

# Compile temp script
ExecWait '"${NSISDIR}\makensis.exe" "$EXEDIR\Installer.nsi"'

Next:
ClearErrors
FindNext $R0 $R1
Goto Loop

Done:
FindClose $R0

# Delete temp script
Delete "$EXEDIR\Installer.nsi"
Abort
FunctionEnd

Section
SectionEnd


Any idea what could be causing the problem?

Silly me.

Forgot to put $\r$\n for the new file writes

Don't worry.

Thanks for all the help!