Archive: InstallOptions as an extension DLL


InstallOptions as an extension DLL
Anybody want to do it, or should I?

Benefits:
* better integration (can subclass and do things like use the normal cancel and next> buttons -- see nsisdl.dll for some good examples)
* better script integration (don't have to write out the HWND, can have items go direct from/to variables)

Downsides:
* have to make sure the DLL frees all memory, since it is running in-process (looks like this can already be done with a #define in installoptions.exe :)

Thoughts, etc? :)

-Justin


Went ahead and got bored and hacked it together.

From the iodll.cpp header:

* key changes
* - no longer need parentwnd ini writing shit
* - to call now, use:
* Push $TEMP\inst.ini
* CallInstDLL $TEMP\mydll.dll dialog
* Pop $0
* ($0 would be "success" "cancel" or some other value on error.
* - new INI entries: [settings]\cancelconfirm (text to confirm cancel on cancel button click)
* - fixed some flag related bugs (multiple of them at 0x100 etc)
* - made it so you can specify positions in negative, for distance from the right/bottom edges.
* - made it so that the file/dir requests automatically size the browse button in
* - removed a lot of code for the old style integration
* - removed support for silent installers (it seems the old version would bring up it's own dialog)


Attached is source and compiled version (in release/)

-Justin


This is a great idea, Justin! :D

Small problem, though. The compiled installer can't be cancelled. You have to choose Next. Why doesn't this work?

I really don't like that old Win3.1ish box you get when you click the Browse button either. Or the useless Read-Only checkbox on it.

Any chance of putting the [Settings]\Title option back in?

Hiding the disabled Back button?


Error with .nsi
The example test.nsi has an error in it. Calls a non-existant label/function "Quit".


Great idea
i was wondering before why install options needed to be a seperate exe, instead of beeing a plugin like nsisdl...

btw Justin, would it be a good idea to make splash.exe a plugin too?
prolly not really any more usefull i suppose...


Originally posted by petersa

I really don't like that old Win3.1ish box you get when you click the Browse button either. Or the useless Read-Only checkbox on it.
Simply add two new flags to the flag table at ReadSettings

{ "FILE_EXPLORER", OFN_EXPLORER },
{ "FILE_HIDEREADONLY", OFN_HIDEREADONLY },


With the FILE_EXPLORER flag you have the new-style dialog box, the FILE_HIDEREADONLY flag ... will hide the readonly checkbox :)

Regards,
~ Florian

maybe a good idea (i hope so):
Maybe it's possible to allready have a window or something at .onInint to be able to use InstOpts there?

But maybe that conflicts with the use of splash, but i don't know, I'm no c expert, sorry...

The reason i'm asking: it would be a lot easier to ask for e.g. RegCodes or something. Right now, i'm using a second installer which has instopts in a section, in my .onInit to ask for RegCode.

Hendri.


Here's an updated DLL+source:


And to those who asks, cancel should work, the result will be "cancel" on the top of the stack (so you can act accordingly in your script).

-Justin

Originally posted by Smile2Me
maybe a good idea (i hope so):
Maybe it's possible to allready have a window or something at .onInint to be able to use InstOpts there?

But maybe that conflicts with the use of splash, but i don't know, I'm no c expert, sorry...

The reason i'm asking: it would be a lot easier to ask for e.g. RegCodes or something. Right now, i'm using a second installer which has instopts in a section, in my .onInit to ask for RegCode.

Hendri.
There are issues with that currently, but that's not to say it couldn't happen soon. I'll work on a solution.


-Justin

OK here's another update. Made the back button optional now, and started upgrading NSIS for better integration. I'll put up nsis 1.9b2 up later today that will really help (a couple of new callbacks and a new instruction). Included in the .zip is an example test-setup.exe, that shows how you can go backwards and forwards..

Something I am thinking is, I want to store the results of a dialog in the ini in such a way so that when you read it back in, the changes you made are saved.

That way, when you go back to a page you already editted, your changes will be preserved. and so on.

The new callbacks I've added to NSIS aren't really right yet. It's a pain figuring out the most general but not painful way to do these things.

-Justin


Here's yet another version, that adds a few options, but the primary difference is that it reads control state information from State=, and writes out the results to the same place (this lets you do neat things like in the example I included). The example I included requires NSIS 1.9b2 which is on www.firehose.net/free/nsis/ (I also included a compiled exe for you to try)

Try this puppy out, let me know what you think.. I suppose I'll clean it up, update the documentation, and all that, unless Michael would rather do it. :)

-Justin


hi justin,

i noticed a little detail in test-setup.exe:
if instopts have been displayed and you continue to select a dir, but then again return to the instopts page, the Next button still says "install"

Greetzzz, Hendri.


hi justin,

sorry, i found the necessary settings to change button text in test.ini...

another thing, we can call instopts after license now. So including RegCode has become possible! Well done!!!

Greetz, Hendri.


Justin,

i think i have found a little bug in InstOpts.dll (that's also in InstOpts.exe BTW):

i use editboxes to get user name and regcode. if these are left blank, then instopts procudes a runtime error.

(at least in my install...)

good luck, greetz, Hendri.


Justin,

two more strange things i noticed using 1.9b2 and instoptsdll4:

-if you use a splash screen, the installer moves to the background suddenly after finishing the splash (no problem in 1.81!)

-if you use .onNextPage and .onPrevPage and program something in these functions (eg a Messagebox, eg after checking RegCode) than the first screen (lisence) appears again, then the message appears and after clicking ok, the page for dirselect appears...

So my order of pages is: lisence agreement, RegCode, DirSelect,...

and using 1.9b2 and instoptsdll4, the installer returns to lisence while checking the code and after that, moves on to DirSelect.

Why is the installer returning to the lisence agreement between page changes?

Greetz, Hendri.


.onNextPage and .onPrevPage work for next/previous screens but what if you wanted to do something on the inital screen?


Originally posted by Hando
.onNextPage and .onPrevPage work for next/previous screens but what if you wanted to do something on the inital screen?
In .onInit do:

BringToFront
CallInstDLL...


BringToFront is necessary because in .onInit the installer window is initially hidden.

-Justin

Originally posted by Smile2Me
Justin,

i think i have found a little bug in InstOpts.dll (that's also in InstOpts.exe BTW):

i use editboxes to get user name and regcode. if these are left blank, then instopts procudes a runtime error.

(at least in my install...)

good luck, greetz, Hendri.
Hmm, empty editboxes don't cause problems for me.. Anything in particular you are doing? Feel free to post your .nsi etc..

-Justin

hi justin,

sorry, nsi not available right now, because i'm not at home...
but this is what i'm doing:

using .onNextPage and .onPrevPage to activate the ini with editboxes using instopts.dll dialog.
Then reading the output of the dll (Pop $R8).
using this to determine what to do (just as in your example...)
The if user has clicked "register", read the ini with readinistr $0 $TEMP\mtlis.ini "FIELD 5" State

And this causes some problem, i think in instopts.dll but maybe it's in my install if you do not experience problems...

Well what I do next:
pass regname and regcode to exe: execwait "check.exe n=$0 c=$1"
and in my exe there's a try environment, so this cannot cause any problem (i guess...)

This exe pushes a 1 if name and code match, a 0 otherwise (eg on error). Then the install checks whether the exitcode of the exe is 1 or 0 and display a message...

But I had some trouble before using this try in a dll (there it didn't do anything so maybe this is the case here, see the thread on RegCode). I will check the source code of my checker, thanks for you response!!

And what about this returning to first page thing??? I want to display a message (eg: Code is ok, thx for registering) but this message appears on top of the lisence agreement (the prev page) and than (after clickin ok) the installer shift to dirselect. This message should be on top of the regname and regcode page, shouldn't it?

Thx for your trouble, greetz, Hendri.


Originally posted by Smile2Me
hi justin,

sorry, nsi not available right now, because i'm not at home...
but this is what i'm doing:

using .onNextPage and .onPrevPage to activate the ini with editboxes using instopts.dll dialog.
Then reading the output of the dll (Pop $R8).
using this to determine what to do (just as in your example...)
The if user has clicked "register", read the ini with readinistr $0 $TEMP\mtlis.ini "FIELD 5" State

And this causes some problem, i think in instopts.dll but maybe it's in my install if you do not experience problems...

Well what I do next:
pass regname and regcode to exe: execwait "check.exe n=$0 c=$1"
and in my exe there's a try environment, so this cannot cause any problem (i guess...)

This exe pushes a 1 if name and code match, a 0 otherwise (eg on error). Then the install checks whether the exitcode of the exe is 1 or 0 and display a message...

But I had some trouble before using this try in a dll (there it didn't do anything so maybe this is the case here, see the thread on RegCode). I will check the source code of my checker, thanks for you response!!
Hmm, I'm not sure why this would cause a crash.. does your code properly handle where the command line has n= and c= (meaning no text after them)...

And what about this returning to first page thing??? I want to display a message (eg: Code is ok, thx for registering) but this message appears on top of the lisence agreement (the prev page) and than (after clickin ok) the installer shift to dirselect. This message should be on top of the regname and regcode page, shouldn't it?

Thx for your trouble, greetz, Hendri.

Ahh this is because you are calling the messagebox from within onNextPage, which is called before the license page is hidden. You could do one of the following:

Probably the first item is nicer looking :) And you can always dynamically generate the ini file using WriteINIStr (so you can include their name and regcode or something like that).

-Justin

-Justin

hi justin,

Quote:


Use installoptions to make the thank-you dialog within the main window.
well i copied the wrong one :)

The above is a great idea!

Greetz, Hendri.

Hi Justin...

I too was having problems with splash screens with NSIS 1.9x, and the new .onNextPage/.onPrevPage functions were /almost/ letting me do something I've wanted to do for ages, so I thought I'd dive in again... :)

How about this..? I've moved .onInit back to where it was, but made .onNextPage triggered before the first page as well as the others. I've also made it possible to jump to any page you like from .onNextPage/.onPrevPage by doing e.g., Abort 2, to go forward 2 pages. Abort 1 in .onNextPage, and Abort -1 in .onPrevPage, would be the same as returning normally without an Abort.

btw, using makensis-bz2.exe saves my installer a whole MB :cool: (down to 7.5MB from 8.5MB).

Dave.


Originally posted by eccles
I too was having problems with splash screens with NSIS 1.9x, and the new .onNextPage/.onPrevPage functions were /almost/ letting me do something I've wanted to do for ages, so I thought I'd dive in again... :)
What exactly is the problem with splash screens in 1.90? They seem to work fine for me.

How about this..? I've moved .onInit back to where it was, but made .onNextPage triggered before the first page as well as the others. I've also made it possible to jump to any page you like from .onNextPage/.onPrevPage by doing e.g., Abort 2, to go forward 2 pages. Abort 1 in .onNextPage, and Abort -1 in .onPrevPage, would be the same as returning normally without an Abort.
Hmm, not sure how I feel about this... I guess being able to skip pages is nice, but it increases teh complexity.. Also, did you need to modify exec.c for Abort -1/1/2? :)

-Justin

I think NSIS needs this sort of functionality built in. The ability to create up to eight pages (it's a bit much but you never know), and you would (with my proposed method) specify the contents as follows:

[code]
; Instead of the SubCaption page_num function, you would just do this:
; If the page name is one of the defaults, "License", "DirSelect", etc. then NSIS should look for the appropriate data here. A page name of "Init" would be the first page displayed in the installer.

Page "License"

PageIn 1 2 ; this is much like SectionIn, it specifies which install type(s) will display this page

SubCaption ": License Agreement" ; Not changed from the default,
; only used to illustrate my idea for a new SubCaption function.

PutText 50,50 "You must agree to the following license before continuing:" ; This replaces the LicenseData function, and allows
; the user to place any text on any page. Syntax: PutText x,y "text"
; where x is the distance from the left and y is the distance from the top

TextBox 50,75 "license.txt" /noedit ; Places a textbox on a page. By
; default it would be editable, so the /noedit switch allows for it
; to be grayed out like the current license agreement.

CheckBox 50,300"I &Agree" AgreeCBox /type=checkbox ; The /type switch
; specifies whether it's a radio button (with radiobuttons, they
; would all be part of the same set for a particular page, meaning
; only one radiobutton could be selected per page.) or a checkbox,
; AgreeCBox is the name which can be called by the VerifyCB function.

PageEnd
Function .onVerifyPage License ; Nice callback. If Abort is called within this, then the Next button for the specified page is greyed out until the condition triggering the abort is no longer true.

VerifyCB $0 AgreeCBox ; Stores the status ("true" for
; checked, "false" for unchecked) of checkbox AgreeCBox
; in user variable $0.
StrCmp $0 "true" UserAgrees
Abort
UserAgrees:
CallPage "DirSelect" ; This would call whatever you want the next page to be.
FunctionEnd


Originally posted by justin
What exactly is the problem with splash screens in 1.90? They seem to work fine for me.
First off, I'm working in XP at the mo, so maybe it's an XP only thing...

I use a modified splash.exe which waits indefinitely. My installer Exec's it, waits for a short pause, brings up a message box, then sends a message to close it afterwards.
  • With NSIS 1.90 the splash screen doesn't become visible until the message box is shown.
  • When it is shown, it appears in front of the message box.
  • Admittedly, I could get around this by sending 0 instead of $HWNDPARENT (?)
Originally posted by justin
Hmm, not sure how I feel about this... I guess being able to skip pages is nice, but it increases teh complexity.. Also, did you need to modify exec.c for Abort -1/1/2? :)

-Justin
Well, did you think I made those earlier savings for nothing? :D

But no - didn't touch it. Only modified ui.c. In some ways it's simpler than before? (.onNextPage/.onPrevPage are only called from one place, for instance.) Have you cast a quick eye over the changes?

Thanks anyway,

Dave.

Fine fine. :)
Since 1.90 was never on nullsoft.com (only firehose.net) I updated it silently.

-Justin


Cheers Justin :)

Dave.


Hi justin,

this is my .onInit:

  File /oname=spltmp.bmp "splash.bmp"
File /oname=spltmp.exe "splash.exe"
ExecWait '"$TEMP\spltmp.exe" 3000 $HWNDPARENT $TEMP\spltmp'
BringToFront
Delete "$TEMP\spltmp.exe"
Delete "$TEMP\spltmp.bmp"


But still my installer moves to the background after finishing splash. So I have to click in the taskbar to activate it again...

Greetz, Hendri.

Hi Hendri...

Have you tried the slightly-modified NSIS 1.90 from firehose.net? .onInit has been moved back to where it used to be (before NSIS creates any windows).

Also, you shouldn't need the BringToFront now. (Actually, maybe this is what's doing the damage now)...

--
Dave.


Dave, thx, i'll download it now.
I didn't realize there was a difference between 1.9 from Nullsoft and that from firehose...

Greetz, Hendri.


it works!!!
hmmm,

now the splash works and the installer doesn't move to the background anymore (I also removed BringToFront)

But also the page numbers have changed!!! so I had to adapt onNextPage and onPrevPage commands...

but it works fine now.

The nice thing about onNextPage and onPrevPage is that it's possible to do something like .onVerifyInstDir but now only after clicking install. So much problems solved!

Thx greetz, Hendri.


Re: it works!!!

Originally posted by Smile2Me
But also the page numbers have changed!!! so I had to adapt onNextPage and onPrevPage commands...

Thx greetz, Hendri.
Sorry about that.. my fault :) They shouldn't change again...

--
Dave.

Dave, thx, it's ok...
the change of page numbers was due to the movement in .onInit,
but i saw the problem and what caused it, so no problems anymore :D.

Now my installer does everything i always wanted it to do:
-Check dir at clicking install
-display splash
-ask for regcode
-create backup
-install the main program into another application
-automatic uninstall if previous version is detected
-and much more....

so i'm happy :)

Maybe, after the 4th of january, Justin will post new possibilities for NSIS and i will get back to work again, but for the moment:

HOLIDAYS!!!

Thx all and greetz, Hendri.


1.90 changes schmanges
Here's what I want to do:
I have a folio of work which I plan to distribute on CD. When the user runs the installer they are given a choice whether they wish to install the folio to their harddrive and run it as an application or run a "lite" (HTML version) from the CD. If the user selects the app version then the installer continues, otherwise I open the webpage and the installer aborts.

Unfortunately the difference between 1.90 at firehose.net and the newer 1.90 has broken my script. With 1.90 from firehose.net I could call the InstallOptions dll with .onInit and the first screen the user saw was my InstallOptions choices page. Now when I compile and run it, it skips the InstallOptions screen and jumps right to the component page.

While I could continue using the older 1.90 I will probably want to take advantage of improvements/features in later releases. So how can I implement this in the new version?


Mmm, sorry about that, my fault again :(

The last couple of 1.9 betas and the original 1.90 broke some installers' splash screens behaviour because they were changed so that .onInit was called after the NSIS window had been created. I submitted a modification which Justin kindly merged in which put the call to .onInit back to where it was (before the NSIS window is created). However, the .onNextPage callback was also changed so that it is also called before the first page (the same place .onInit was called in the original 1.90), so you can move your call to InstallOptions to the .onNextPage function to get the same behaviour as before. The only other change you'll need is to set a flag (in .onInit) and test for it before showing InstallOptions, as .onNextPage is called for every page change.

Function .onInit
StrCpy $9 ""
FunctionEnd

Function .onNextPage
StrCmp $9 "" isFirstPage
Return
isFirstPage:
StrCpy $9 "Y"
; Do InstallOptions stuff
FunctionEnd

HTH

--
Dave.

thanx
problem solvered!



Call HideWindow, then MessageBox, and then BringToFront at the end. (this will hide the main install window while it displays the messagebox).

Probably the first item is nicer looking And you can always dynamically generate the ini file using WriteINIStr (so you can include their name and regcode or something like that). This is a great idea! I will implement it when i get home, after first completing my final exam of Applied Microeconomics :(

I will also check whether my check.exe handles empty strings allright. I allready tested this a little bit and did not find problems. Maybe there is something I overlooked...

But this should be caught by try (if it does work...) I'll test some more :)

Thx, greetz, Hendri.