- NSIS Discussion
- To start from a specified folder by Browse button in Directory Page
Archive: To start from a specified folder by Browse button in Directory Page
Maxim30
22nd May 2010 21:13 UTC
To start from a specified folder by Browse button in Directory Page
Hello,
in the Directory Page, I would start from a specified folder when clicking the Browse button instead to start from the User directory and would also keep the directory structure tree completely so setup user can choose among all disk directories instead from only the tree of the specified folder.
How to make it ? Which is the code ?
Animaether
23rd May 2010 20:53 UTC
Originally posted by Maxim30
in the Directory Page, I would start from a specified folder when clicking the Browse button instead to start from the User directory
bland NSIS, use...
Var myDirVar
Function .onInit
StrCpy $myDirVar "$PROGRAMFILES\NSIS\"
FunctionEnd
PageEx directory
DirVar $myDirVar
PageExEnd
MUI2, use...
myDirVar
Function .onInit
StrCpy $myDirVar "$PROGRAMFILES\NSIS\"
FunctionEnd
!define MUI_DIRECTORYPAGE_VARIABLE $myDirVar
!insertmacro MUI_PAGE_DIRECTORY
nsDialogs (manually calling the code), use...
nsDialogs::SelectFolderDialog "Title" "$PROGRAMFILES\NSIS\"
Originally posted by Maxim30
and would also keep the directory structure tree completely so setup user can choose among all disk directories instead from only the tree of the specified folder.
Not sure what you mean by that - but if you mean 'expand all the folders and subfolders on the user's entire drive'... bad idea ;) Just let the user expand if they desire to install to a specific location.
Maxim30
24th May 2010 05:10 UTC
I mean to show to user the starting folder I preset and from there he/she can choose (expanding or not) any other directory.
The MUI2 version code works as I want.
But additionaly in my script I have the following code:
this first functon to determine whether a previous installation was made and then whether the system is 32 or 64 bit ...
Function MyGUIInit
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${Nome}" "NSIS:InstallDir"
${If} $0 != ""
StrCpy $INSTDIR $0
${ElseIf} ${RunningX64}
StrCpy $INSTDIR "$PROGRAMFILES64\${Nome}"
${Else}
StrCpy $INSTDIR "$PROGRAMFILES32\${Nome}"
${EndIf}
Function End
and this second function to append always the string ${Nome} to the choosen path ...
Function .onVerifyInstDir
${WordAdd} "$INSTDIR" "\" "+${Nome}" $INSTDIR
FunctionEnd
And instead with my two functions above the MUI2 code you proposed does not work, starting the installation folder still always from User directory; if I write only $PROGRAMFILES64 (and $PROGRAMFILES32) instead of $PROGRAMFILES64\${Nome} (and $PROGRAMFILES32\${Nome}) then the code works as I want.
How to fix my code above with yours ?
Animaether
24th May 2010 08:48 UTC
the reason that doesn't work is because the folder selection dialog can only be pointed to folders that exist. So when you append ${Nome} (let's say its value is 'myDir'), then $PROGRAMFILES\myDir\ must be a folder that exists for the browser to open in that location.
The simplest solution would be to browse to the main folder (in this case, $PROGRAMFILES), and append the ${Nome} at a later point.
Maxim30
24th May 2010 11:27 UTC
Or alternatively I could append the string ${Nome} only when the Directory Page Browse button is clicked.
How can I add/modify actions when the Browse button is clicked ?
Animaether
24th May 2010 11:56 UTC
I don't think there are specific callbacks for the user pressing the browse button or having selected a folder in MUI2. You could easily set something up using a custom dialog, though.
Maxim30
24th May 2010 12:05 UTC
And do they exist for normal MUI ?
Animaether
24th May 2010 13:25 UTC
You could have a peek at the .onVerifyInstDir callback - that gets called whenever the user changes the installation directory; should be able to use that with MUI2 as well, come to think of it.
Maxim30
25th May 2010 09:23 UTC
Ok. If I use the instructions FindWindow and GetDlgItem on the Browse button, how can I write the code to have the installer to open the $PROGRAMFILES32 (or $PROGRAMFILES64) folder instead of preset $PROGRAMFILES32\${Nome} (or $PROGRAMFILES64\${Nome}) every time user click on the Browse button ?
Animaether
25th May 2010 12:19 UTC
You don't use that - you just use the $myDirVar (or $INSTDIR if you're not using the custom dir var ).
For example:
!include "nsDialogs.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
Section
SectionEnd
!define Nome "NSIS"
Var myDirVar
!define MUI_DIRECTORYPAGE_VARIABLE $myDirVar
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE myFunction
!insertmacro MUI_PAGE_DIRECTORY
Function .onInit
; Default install location / install location read from registry
StrCpy $myDirVar "$PROGRAMFILES\"
FunctionEnd
Function myFunction
StrCpy $INSTDIR "$myDirVar\${Nome}"
MessageBox MB_OK "User selected install location: '$myDirVar'$\r$\nActually installing to: '$INSTDIR'"
FunctionEnd
!insertmacro MUI_LANGUAGE "English"
Maxim30
25th May 2010 13:45 UTC
In any case how can I write a code to perform an action after clicking the Browse button in the Directory Page ?
Animaether
25th May 2010 14:35 UTC
!include "LogicLib.nsh"
!include "nsDialogs.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
Section
SectionEnd
!define Nome "NSIS"
Var myDirVar
!define MUI_DIRECTORYPAGE_VARIABLE $myDirVar
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE myFunction
!insertmacro MUI_PAGE_DIRECTORY
Function .onInit
; Default install location / install location read from registry
StrCpy $myDirVar "$PROGRAMFILES\"
FunctionEnd
Function .onVerifyInstDir
${If} "$myDirVar" == "$DESKTOP"
MessageBox MB_OK "User clicked browse button (or manually entered desktop location"
${EndIf}
FunctionEnd
Function myFunction
StrCpy $INSTDIR "$myDirVar\${Nome}"
MessageBox MB_OK "User selected install location: '$myDirVar'$\r$\nActually installing to: '$INSTDIR'"
FunctionEnd
!insertmacro MUI_LANGUAGE "English"
But that is a hack.. .onVerifyInstDir gets a message for every folder change within the dialog (and the user typing in the main field); it assumes that the first folder opening when the user presses the browse button is the Desktop folder.
If you want better control, you'd want to use nsDialogs to build your own dialog.
But, again, you're not going to be able to manipulate much in the browse dialog.
Maxim30
25th May 2010 15:05 UTC
I have tried this code but it does not work as I want:
!define MUI_PAGE_CUSTOMFUNCTION_SHOW MyDirPage
...
Function MyGUIInit
GetFunctionAddress $3 MyNewFolder ; get address of MyNewFolder function
FunctionEnd
Function MyDirPage
FindWindow $1 "#32770" "" $HWNDPARENT
GetDlgItem $2 $1 1001 ; Get Browse button Dialog Item
nsDialogs::OnClick $2 $3 ; checks clicks on Browse button and calls MyNewFolder function
FunctionEnd
Function MyNewFolder
; appropriate instructions here
MessageBox MB_OK "Browse button clicked" ; test by now
FunctionEnd
Function .onVerifyInstDir
${WordAdd} "$INSTDIR" "\" "+${Nome}" $INSTDIR ; appends string ${Nome} to the choosen path by Browse button
FunctionEnd
The GetDlgItem instruction works because I tested it with the instruction "EnableWindow $2 0" (disable Browse button). But the function MyNewFolder seems to not work because the MessageBox test is never shown:
are the variables $2, $3 and the instructions GetFunctionAddress, nsDialogs::OnClick correct ?
Animaether
25th May 2010 15:52 UTC
I don't think you can use nsDialogs' event handlers on existing buttons.
I'm also somewhat confused by what you're actually trying to do.
You want the Browse dialog to open in a specific location, in this case $PROGRAMFILES. Then when the user has selected a folder, you want to append ${Nome}. Is that correct? If so - then the example two posts back should be all that you need.
If you also want to -show- the user that you appended ${Nome}, then you'd have to check if the text on the directory input field has changed, append ${Nome} if it's not already appended, etc. etc.
( all of which is a lot easier with a custom dialog )
Maxim30
25th May 2010 16:20 UTC
Yes, I want to append the string ${Nome} at end of the path choosen by user, and I have realized it.
Furtherly when user clicks on Browse button I want to show to him/her the $PROGRAMFILES32 or $PROGRAMFILES64 folder (and then its subfolders branch too) instead to show to him/her the default User folder, but I have not realized it: how to make it ?
Afrow UK
25th May 2010 17:58 UTC
As far as I can see (at least on Windows 7) the Browse dialog never opens to the currently chosen install directory. Is this not the case on XP? I suggest you post a feature request or add the feature yourself.
Stu
Maxim30
25th May 2010 18:14 UTC
Really clicking on the Browse button the current install folder is opened (with its subfolders branch) if it is existing, and this is I want.
Instead if it is not existing then the User folder is opened (default), and this is not I want; I am seaching to open at least the $programfiles32 or $programfiles64 folders in this case, and perhaps it is possible using the nsDislogs::OnClick instruction: is it ?
DrO
25th May 2010 18:37 UTC
you're pretty much going to have to edit/make some code to do what you're wanting - it's relatively simple as the callback function to the SHBrowseForFolder just needs to be adjusted to change to a different folder path if the first isn't valid though i've no idea where in NSIS that is being done (which probably doesn't help) but it's a trivial thing to do in response to the BFFM_INITIALIZED message in the OS api's callback function.
-daz
Animaether
25th May 2010 19:04 UTC
Or you can just change the folder passed to the browse dialog when the folder doesn't exist - you can check all of this with NSIS -before- you open the dialog.
( This works fine in Windows 7 as well )
Expanding that folder or the nodes in the tree below that folder, however, is another matter entirely; in theory it can be done, but you'd probably have to change the code (unless a tricky nsDialogs timer could send the command to expand the currently selected item in the tree).
!include "LogicLib.nsh"
!include "nsDialogs.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
Section
SectionEnd
Var myDirVar
!define MUI_DIRECTORYPAGE_VARIABLE $myDirVar
!insertmacro MUI_PAGE_DIRECTORY
Function .onInit
${If} ${FileExists} "$PROGRAMFILES\SomeFolder\*.*"
StrCpy $myDirVar "$PROGRAMFILES\SomeFolder\"
${Else}
StrCpy $myDirVar "$PROGRAMFILES\"
${EndIf}
FunctionEnd
!insertmacro MUI_LANGUAGE "English"
DrO
25th May 2010 20:14 UTC
or that approach :) (had thought it had already been tried though i did only skim through to the end of the thread).
-daz
Maxim30
25th May 2010 21:32 UTC
I reexplain the situation:
at setup start I have as shown in attached screenshot 1: what I have and also wanted.
After clicking on the Browse button I would as shown in attached screenshot 2: what wanted.
After clicking on Browse button I have instead as shown in attached screenshot 3: what I get now instead and to avoid.
Afrow UK
25th May 2010 21:33 UTC
Yeh we get it. Did you try Animaether's code?
Stu
Maxim30
25th May 2010 22:34 UTC
Originally posted by Afrow UK
Yeh we get it. Did you try Animaether's code?
Stu
No. Which of the last three should I try ?
Afrow UK
25th May 2010 23:15 UTC
Try the last one he posted:
http://forums.winamp.com/showpost.ph...0&postcount=19
Stu
Maxim30
26th May 2010 03:53 UTC
The statement
${If} ${FileExists} "$PROGRAMFILES\SomeFolder\*.*"
is always false because my prompted folder is new non existent so there is not a special in the code, it does nothing.
Afrow UK
26th May 2010 09:31 UTC
Did you try it or not? There's an ELSE statement in the code in case you didn't see it.
Edit: I have tried it and it works.
Stu
Afrow UK
26th May 2010 09:46 UTC
However, it is the same as just using InstallDir $PROGRAMFILES. This is what I said initially: whatever is in the directory box AND IT EXISTS will cause the Browse dialog to open to it. If the path does not exist then Browse will go to the default (root/user). So the only thing you can do is set InstallDir $PROGRAMFILES and then perhaps add:
Function .onVerifyInstDir
StrCpy $INSTDIR `$INSTDIR\${Name}`
FunctionEnd
This will ensure your app name is appended to the end (use if you need that to happen). Notice that when you click Browse again you are back to root!
I think if you want to do this properly you need to change NSIS itself or post a feature request - i.e. get Browse to open in the parent folder of the current install directory if that exists, or go to the parent of that if it exists etc
Stu
Maxim30
26th May 2010 11:03 UTC
Originally posted by Afrow UK
However, it is the same as just using InstallDir $PROGRAMFILES. This is what I said initially: whatever is in the directory box AND IT EXISTS will cause the Browse dialog to open to it. If the path does not exist then Browse will go to the default (root/user). So the only thing you can do is set InstallDir $PROGRAMFILES and then perhaps add:
Function .onVerifyInstDir
StrCpy $INSTDIR `$INSTDIR\${Name}`
FunctionEnd
This will ensure your app name is appended to the end (use if you need that to happen). Notice that when you click Browse again you are back to root!
I think if you want to do this properly you need to change NSIS itself or post a feature request - i.e. get Browse to open in the parent folder of the current install directory if that exists, or go to the parent of that if it exists etc
Stu
Yes, I think it is better to post a feature request to make Browse to open in the parent folder of the current install directory if the last path portion is not existent.
Afrow UK
26th May 2010 12:21 UTC
http://nsis.sourceforge.net/Requests
Stu
Animaether
26th May 2010 13:36 UTC
!include "LogicLib.nsh"
!include "nsDialogs.nsh"
!include "MUI2.nsh"
!include "FileFunc.nsh"
OutFile "test.exe"
Section
SectionEnd
Var myDirVar
!define MUI_DIRECTORYPAGE_VARIABLE $myDirVar
!insertmacro MUI_PAGE_DIRECTORY
Function .onInit
StrCpy $myDirVar "$PROGRAMFILES\NSIS\ExampleZ\"
${GetRoot} "$myDirVar" $0
${DoUntil} ${FileExists} "$myDirVar"
${GetParent} "$myDirVar" $myDirVar
${Loop}
${If} "$myDirVar" == "$0"
/* Installation would end up in ROOT. Switching to default instead. */
StrCpy $myDirVar "$PROGRAMFILES"
${EndIf}
StrCpy $myDirVar "$myDirVar\"
FunctionEnd
!insertmacro MUI_LANGUAGE "English"
Afrow UK
26th May 2010 14:12 UTC
Animaether, the point is this needs to be done when you Browse. As soon as you enter a non existent path on the directory page the browse dialog always starts at the root.
Edit:
i.e. if you have $PROGRAMFILES\MyApp as InstallDir or upon directory selection or manual entry Browse should open initially to $PROGRAMFILES if MyApp does not exist.
Stu
Animaether
26th May 2010 15:17 UTC
The only case in which things wouldn't work as desired is when the user enters a non-existing path on the directory page itself; the directory browser doesn't let you pick non-existing paths.
So, again, it'd be a lot easier to handle with a custom page - as in that case the directory browser doesn't grab the data from the entry field as authoritative and you can manipulate the path for the directory browser before opening it.
I'm not saying that the feature request isn't valid - just suggesting ways in which one can do the desired with the tools already at one's disposal.