- NSIS Discussion
- Custom Install Options Page based off directory contents...
Archive: Custom Install Options Page based off directory contents...
Dick4
7th March 2003 16:50 UTC
Custom Install Options Page based off directory contents...
I'm trying to create a custom Install Options page that has 2 fields, one being a label and one being a listbox. The only thing is, I'd like the list box to be filled with contents of a directory. I read the instructions (and searched, btw ;)) on how to add stuff to the ini file, but how would I get the directory contents through NSIS?
Alternatively, I created a vbscript that creates the ini file completely (with directory contents loaded into it), but I don't know if/how I could execute this vbscript to create the ini file...and would NSIS even like that because the INI file wouldn't be packaged with it, but it would be referenced...
Here is the INI file...the listItems line is the one I am creating at run time:
[Settings]
NumFields=2
NextButtonText=Next
[Field 1]
Type=label
Text=Choose the database to repair from the list:
Left=0
Right=-1
Top=0
Bottom=10
[Field 2]
Type=DropList
ListItems=1775|1776|1777|
Left=0
Right=-100
Top=10
Bottom=100
kichik
7th March 2003 17:22 UTC
Use FindFirst, FindNext and FindClose.
You can find an example here:
http://nsis.sourceforge.net/archive/....php?pageid=58
To write to INI files just use WriteINIStr.
Dick4
7th March 2003 18:06 UTC
is there a quick tutorial somewhere on what Push and Pop do? I tried to figure them out before (because I use the GetParent function) but never really got the hang of it..
Sunjammer
7th March 2003 18:10 UTC
Push and Pop "push" and "pop" values onto and off a stack of values. Imagine a stack of plates, you add a plate to the top of the stack by pushing it on, and you remove the top plate on the stack by "pop"ing it off. So, push and pop just give you somewhere to store values. If you push 5 then 4 then 8 when you do three pops you will get the values back in reverse order (think about the plates analogy and you'll see why) i.e. 8, 4 then 5.
Example Code:-
Push 5
Push 4
Push 8
Pop $0
Pop $1
Pop $2
You would now have the value 8 in the variable $0, the value 4 in the variable $1 and the value 5 in variable $2. You can push anything, e.g.
Push "My string"
Push $1
Push $R3
Note: There is only one stack for the entire time your installer runs, so if you Push 5 at the very start it will still be there at the end if you haven't Pop'd it off the stack. It doesn't matter if you enter a function or a section or whatever, you'll still be manipulating the same stack as any other place or time in the script.
Dick4
7th March 2003 18:16 UTC
ok, to take the GetParent analogy...first I do
Push $INSTDIR
Call GetParent
Pop $0
Push $INSTDIR puts the INSTDIR on the top of the stack, then, when in the GetParent function I say:
Exch $0
I'm really "calling" the top item on the stack, whatever that may be...effectively returning my install directory to $0. But then the next 2 lines read:
Push $1
Push $2
$1 and $2 are empty at this point, so what gets put on the stack? Their empty variables? which are filled later?
Sunjammer
7th March 2003 18:20 UTC
In your example Exch $0 swaps the top item on the stack with whatever value $0 contained. The value that was on the stack top before is now stored in $0, and the value that was in $0 is now the top value on the stack.
If $1 and $2 are empty before the Pushes then empty values will be pushed onto the top of the stack. Pushing *never* changes the value pushed so why would you expect $0 or $1 to be different at some later time?
If instead you said
StrCpy $0 "My example string"
Push $0
Then you might be pushing something useful onto the stack rather than an empty value.
Sunjammer
7th March 2003 18:21 UTC
Another note, the Exch $0 (a) gets you the value pushed onto the stack by GetParent and stores it in $0 (b) saves whatever value you had in $0 before calling Exch onto the top of the stack. If you didn't care about the value in $0 before calling Exch you could use Pop $0 instead of Exch $0.
Dick4
7th March 2003 18:26 UTC
ok...I actually was just reading the documentation on "Exch", but I understand your analogy better.
I took the "Push $1" and $2 lines from the GetParent, but I think I see how that is working. Now relating that to my issue, I need to create a line in the INI file with a string of all the file names in that directory (preferably all the .mdb file names, but that can come later). Using the function Kichik pointed to above, it appears I would have to fill a variable with a running list of my files. In vb I would do this via fileStr = fileStr + "|" + newFile. Then, in the end write the INI file using fileStr as my string to write. Is this how I should be going about doing this? And how would I do it in NSIS?
kichik
7th March 2003 18:30 UTC
Push $1 and Push $2 are there so when a user calls this function it won't ruin his variables. Unless you are going to create a function out of this code you don't need it.
Yes, you should create the line and then write it. To append text to an existing variable use:
StrCpy
$0"$0|moretext..."
This will copy "$0|more text..." into $0 and therefore appending "more text..." to $0.
Sunjammer
7th March 2003 18:32 UTC
Yup InstallOptions requires you to use | to separate the list items. You want something like (untested) :-
FindFirst $0 $1 "c:\path\to\my\files\*.mdb"
StrCpy $9 ""
StrCmp $0 "" error
again:
StrCmp $1 "" done
StrCmp $9 "" 0 append
StrCpy $9 $1
Goto readnext
append:
StrCpy $9 "$9|$1"
readnext:
FindNext $0 $1
Goto again
done:
FindClose $0
; now write to the ini file
WriteIniStr "filename.ini" "section_name" "ListItems" $9
goto finished
error:
; hmmm
finished:
Dick4
7th March 2003 18:58 UTC
Ok, I have a better grasp of what's going on, but I can't figure this out. I have either of 2 functions right now, neither work (one is yours, Sunjammer, the other is the one Kichik linked to).
Function GetFiles
Exch $1 ; Dir
Push $2
Push $3
FindFirst $2 $3 "$1\*.*"
StrCmp $3 "" exitloop
loop:
StrCmp $3 "" exitloop
StrCmp $3 "." next
StrCmp $3 ".." next
IfFileExists "$1\$3\*.*" next
; Append each file to the eventual listitem variable
StrCpy $4 "$4|$1\$3"
next:
FindNext $2 $3
Goto loop
exitloop:
FindClose $2
WriteINIStr "ioA.ini" "[Field 2]" "ListItems" $4
Pop $3
Pop $2
Pop $1
FunctionEnd
Function GetFiles2
FindFirst $0 $1 "C:\Payroll\client\*.mdb"
StrCpy $9 ""
StrCmp $0 "" error
again:
StrCmp $1 "" done
StrCmp $9 "" 0 append
StrCpy $9 $1
Goto readnext
append:
StrCpy $9 "$9|$1"
readnext:
FindNext $0 $1
Goto again
done:
FindClose $0
; now write to the ini file
WriteINIStr "ioA.ini" "[Field 2]" "ListItems" $9
goto finished
error:
; hmmm
finished:
FunctionEnd
With the GetFiles one, this is my section
Section "Add Files to Drop Down List"
Push $INSTDIR
Call GetFiles
Sectionend
Dick4
7th March 2003 19:00 UTC
by the way, I thank you guys so much for all your help so far...you've been amazing (as always :))
kichik
7th March 2003 19:10 UTC
I replace the WriteINIStr with DetailPrint $9 and both gave the right output. You probably didn't give the right path to the INI file. If it's in $PLUGINSDIR use the IO macro or just write $PLUGINSDIR\ioA.ini, if not append the right path.
Dick4
7th March 2003 19:17 UTC
ok, well, Its just getting extracted to wherever they get extracted to by default. I tried the DetailPrint and did also see that it was working right, but its still not getting into the ini file...
checking it now...this is my extract statement, btw...if it matters.
;Extract InstallOptions INI Files
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "ioA.ini"
kichik
7th March 2003 19:20 UTC
If you are using this macro then it goes into $PLUGINSDIR. Use its friend MUI_INSTALLOPTIONS_WRITE :)
Dick4
7th March 2003 19:21 UTC
ok, I am...trying that now...I found the ini file with the installoptions.dll file in a subfolder in my temp dir.
kichik
7th March 2003 19:22 UTC
Yep, that's where $PLUGINSDIR hides.
Dick4
7th March 2003 19:29 UTC
that didn't seem to work, either. The NSI file is available here if you want to see that
http://webpages.charter.net/dick4/files/JetComp.nsi
kichik
7th March 2003 19:35 UTC
This line is wrong:
!insertmacro MUI_INSTALLOPTIONS_WRITE "$PLUGINSDIR\ioA.ini" "[Field 2]" "ListItems" $9
It's either the macro or $PLUGINSDIR, not both. The macro adds $PLUGINSDIR_by itself.
Sunjammer
7th March 2003 19:35 UTC
Wow you mean to say that my cobbled together thoughts actually amounted to something usable? I'm amazed :P
Dick4
7th March 2003 19:38 UTC
I tried that, its still not doing it right...tried it both ways
kichik
7th March 2003 19:42 UTC
Ah, there is anoter mistake in that line. The section name isn't "[Field 2]", it's "Field 2". The brackets mark the line being a section opening line. So it should be:
!insertmacro MUI_INSTALLOPTIONS_WRITE "ioA.ini" "Field 2" "ListItems" $9
Dick4
7th March 2003 19:51 UTC
You're right...but its still not working...crap!
kichik
7th March 2003 19:52 UTC
Does it show $9 in the details window? Can you attach the latest script too please?
Joost Verburg
7th March 2003 19:56 UTC
Also check what is written to the INI file in the plugins dir.
Dick4
7th March 2003 19:58 UTC
http://webpages.charter.net/dick4/files/JetComp.nsi
INI file, too...if needed: http://webpages.charter.net/dick4/files/ioA.ini
I updated with the latest script and yes, it is showing correctly in the details
*edit* the ListItems line in INI file in the plugins directory is just like the original...no change has been made to it.
kichik
7th March 2003 20:02 UTC
Ah... You are calling the function after the page was shown. Call it before MUI_INSTALLOPTIONS_DISPLAY in the SetCustomA function.
Dick4
7th March 2003 20:10 UTC
Ok, that did it...now my only problem is that this path can change...it should be a path read from the registry...but with my current code:
Function SetCustomA
Call GetFiles2
!insertmacro MUI_HEADER_TEXT "$(TEXT_IO_TITLE)" "$(TEXT_IO_SUBTITLE)"
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "ioA.ini"
FunctionEnd
I'm figuring it out before I get to that part of my code. Is there any way to do what I want? I want to figure that drop down list AFTER I've figured out my $INSTDIR (and actually, after that because i need to get the parent dir of the $INSTDIR)
kichik
7th March 2003 20:11 UTC
Make this page show after the user has selected the installation directory. Then all you'll need to do is get the parent in this function and you're set.
Dick4
7th March 2003 20:44 UTC
But I don't have a directory choosing page...do I need one to do this? I've been trying to do it all in one section and it doesn't appear to be working...
kichik
7th March 2003 20:46 UTC
As sections are called after those pages are shown you can't set settings for the custom page in them. If you don't have a directory selection page then $INSTDIR is set right of the begning of the installer you should have no trouble using it in SetCustomA. If you need to work on $INSTDIR before the page shows do it in .onInit.
Dick4
7th March 2003 21:29 UTC
that worked, btw...thanks a ton!
I thought .onInit happened before anything else...is it listed somewhere the order in which everything happens?
kichik
7th March 2003 21:36 UTC
The exact order is not listed anywhere, but in every callback function docs it's mentioned when it's exectued, sections are executed in the instfiles page, and non-callback functions when called.