Archive: Set installation dir according to a value from an ini


Set installation dir according to a value from an ini
Hi to all.

I was an innosetup user but decided to use nsis for some reasons. Some things are different... Anyway my problem is:

Installer should read from "XXX.ini" file to detect if TargetProgram installed for multi user profile or not. Then it should copy files to right directory. XXX.ini has these lines:

[System]
Multi User=1 or 0

if "Multi User"=1 ==> installer should understand that TargetProgram is installed for multi profile so target directory is $appdata
if "Multi User"=0 ==> installer should understand that TargetProgram is installed for single profile so target directory is $INSTDIR


Section part:
SectionGroup "Sectin1" SecMenu
Section "-"
SetOutPath "$SPECIAL_DIR"
SetOverwrite on
File Dosyalar\lang1.lng
File Dosyalar\lang2.lng
SetOutPath "$SPECIAL_DIR\skin\"
File Dosyalar\MySkin.zip
SetOutPath "$SPECIAL_DIR\toolbar\"
File Dosyalar\toolbar.ini
SectionEnd


$SPECIAL_DIR can changable acording to he XXX.ini. It may $appdata or $instdir.

How can i do nsis make this?

One more thing that, my installer doesn't overwrite files. It doesn't even warn me. I've added "SetOverwrite on" but nothing was changed...

After spending all day on help file and forums couldn't find special for this situation.


ReadINIStr and StrCpy

ReadINIStr $R0 "path\to\file.ini" "System" "Multi User"
StrCmp $R0 1 0 +3
StrCpy $SPECIAL_DIR $APPDATA
Goto +2
StrCpy $SPECIAL_DIR $INSTDIR

-Stu


Thank you very much but i got this error:

StrCmp "$R0" "1" equal=0, nonequal=+3
Usage: StrCpy $(user_var: output) str [maxlen] [startoffset]
There may be something i missed...

Did you declare SPECIAL_DIR with the Var instruction?

Var SPECIAL_DIR

-Stu


Of course did not. I forgot, sorry...

Now, i have another problem. I've done a test script and i've put a test.ini in C:\ with [System] and Multi User=1 values.

var SPECIAL_DIR
Function TestFunction
ReadINIStr $R0 "C:\Test.ini" "System" "Multi User"
StrCmp $R0 1 0 +3
StrCpy $SPECIAL_DIR $APPDATA
Goto +2
StrCpy $SPECIAL_DIR $INSTDIR
FunctionEnd

SectionGroup "!Test Section" SecMainMenu
Section "-Hidden"
SectionIn RO
SetOutPath "$INSTDIR"
SetOverwrite on
File Dosyalar\Lang1.lng
File Dosyalar\Lang2.lng
SetOutPath "$INSTDIR\skin\"
File Dosyalar\MySkin.zip
CreateDirectory "$SPECIAL_DIR\Test\toolbar"
SetOutPath "$SPECIAL_DIR\Test\toolbar\"
File Dosyalar\toolbar.ini
SectionEnd
.
.
.
SectionGroupEnd
I got this error while installing:
http://img93.imageshack.us/img93/3856/hata4ed.png
I couldn't make SPECIAL_DIR work. It returns with no string...

Are you even calling TestFunction? Just rename it to .onInit

-Stu


Ok, thanks. It works now on my test script but i can't run on my installer's script. There are several lines under .onInit section. Do you think that they may prevent to run this one?

Another question: I've noticed that, target .ini file's related line has a comment. I mean that line we want to get is like this:
[System]
Multi User=1 ; If enabled program will use Windows profiles to store individual user settings

How can i get just integer from this line?

And last question is, if there is no target.ini or no value in it, can i set an alternate installation path?


I'm not sure why but NSIS doesn't seem to handle comments very well when they're placed on the same lines as property values, even though NSIS uses Windows API's (I think).

Use this function:
http://nsis.sourceforge.net/Get_first_part_of_a_string

ReadINIStr $R0 "path\to\file.ini" "System" "Multi User"
StrCmp $R0 "" 0 +3
StrCpy $SPECIAL_DIR "my path"
Goto End
Push $R0
Call GetFirstStrPart
Pop $R0
StrCmp $R0 1 0 End
StrCpy $SPECIAL_DIR $APPDATA
Goto End
StrCpy $SPECIAL_DIR $INSTDIR
End:


-Stu

Thank you very much.

Btw, is there any editor like program which has highlighting feature? It could make easier to write script...


Almost everyone uses HM NIS Edit. It is freeware and open source, and has syntax highlighting and an installoptions editor. The link above takes you to the mirrors page to download it.


If you want to stick with Notepad like me, you can try Notepad2:
http://www.flos-freeware.ch/notepad2.html

It has built in highlighting for many programming languages including NSIS.

-Stu


These codes are interesting. I've set some part of hasmetlee's and Afrow UK's codes for me and tried to run but some part of my script didn't work.

It can copy MyApp.ini file, so "section" part did work but ---InstallDir "$My_Path_01\MyApp"--- part didn't work. Tell me please what's wrong?

  !include "MUI.nsh"
!include "Sections.nsh"

Name "MyApp"
OutFile "MyApp.exe"

Function GetFirstStrPart
Exch $R0
Push $R1
Push $R2
StrLen $R1 $R0
IntOp $R1 $R1 + 1
loop:
IntOp $R1 $R1 - 1
StrCpy $R2 $R0 1 -$R1
StrCmp $R2 "" exit2
StrCmp $R2 " " exit1 ; Change " " to "\" if ur inputting dir path str
Goto loop
exit1:
StrCpy $R0 $R0 -$R1
exit2:
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

Var My_Path_01
Function .onInit
ReadINIStr $R0 "C:\Test.ini" "AppDir" "MultiOrNot"
StrCmp $R0 "" 0 +3
StrCpy $My_Path_01 "$APPDATA\My_Path_02"
Goto End
Push $R0
Call GetFirstStrPart
Pop $R0
StrCmp $R0 1 0 End
StrCpy $My_Path_01 $APPDATA
Goto End
StrCpy $My_Path_01 $INSTDIR
End:

StrCpy $1 ${FGVar}

!insertmacro MUI_LANGDLL_DISPLAY

FunctionEnd
Function .onSelChange

!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${FGVar}
!insertmacro RadioButton ${FGYok}
!insertmacro EndRadioButtons

FunctionEnd

SectionGroup "!Test Section" SecMainMenu
Section "Hidden"
SectionIn RO
SetOutPath "$My_Path_01\MyApp"
File MyApp.ini
SectionEnd
SectionGroupEnd

InstallDir "$My_Path_01\MyApp"


!insertmacro MUI_PAGE_DIRECTORY
ShowInstDetails show
AutoCloseWindow false

I'm assuming then that InstallDir sets a fixed path for the installation directory. This is a constant value specified at compile time which cannot contain variables (or can, but they are ignored, correct?)

It appears that you're not even using the $INSTDIR variable which is pre-defined to store the path for where to install files too. Therefore, rather than using $My_Path_01, just use $INSTDIR! You won't even need to use the InstallDir instruction then, because the value of $INSTDIR is what is displayed on the directory page.

-Stu


Thanks for the program links and the informations...


Well I may be wrong, but if InstallDir does accept variables then it wouldn't matter anyway because you are setting the value of $My_Path_01 in .onInit. InstallDir sets the default value of $INSTDIR before .onInit. Therefore, I would have though that any variables specified in InstallDir will just be an empty string.

That's why you should be using $INSTDIR as it sets the InstallDir directly.

What installation directory do you get on the directory page? Is it "\MyApp" or "$My_Path_01\MyApp"?

-Stu


I've just noticed about this...

If target .ini file has zero value script doesn't work:
[System]
Multi User=0 ;comment section....
But if "Multi User=1" ==> it works... Why? What's wrong?

One more thing that, if there is no target.ini file or there is no "Multi User" line in it, my installer has %100 CPU usage. This one is a rarely situation but i have to take care all of these... How can i prevent this and make my script work?

I've cleaned up my script, here is a light version of it:


!include "MUI.nsh"
!include "Sections.nsh"

Var Yol ;Yol

;--------------------------------
Name "My Prog"
OutFile "Deneme.exe"
InstallDir "$PROGRAMFILES\Opera"
InstallDirRegKey HKCU "Software\Opera Software" "Last Directory3"

ShowInstDetails show
AutoCloseWindow false
SilentInstall normal
CRCCheck on
SetCompressor /solid "lzma"
SetDatablockOptimize on
SetOverwrite on

;--------------------------------
;Görünüm

;!define MUI_HEADERIMAGE
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico"
!define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\orange.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\Orange.bmp"
!define MUI_COMPONENTSPAGE_CHECKBITMAP "${NSISDIR}\Contrib\Graphics\Checks\colorful.bmp"
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN $INSTDIR\Opera.exe
!define MUI_ABORTWARNING

;--------------------------------
;Pages

!insertmacro MUI_PAGE_INSTFILES

;--------------------------------
;Installer Sections
SectionGroup "Section Main" SecMenu
Section "!Needed files"
SectionIn RO
SetOutPath "$Yol\toolbar\"
File Dosyalar\toolbar.ini
SectionEnd
SectionGroupEnd

;--------------------------------
;Functions

Function GetFirstStrPart
Exch $R0
Push $R1
Push $R2
StrLen $R1 $R0
IntOp $R1 $R1 + 1
loop:
IntOp $R1 $R1 - 1
StrCpy $R2 $R0 1 -$R1
StrCmp $R2 "" exit2
StrCmp $R2 " " exit1 ; Change " " to "\" if ur inputting dir path str
Goto loop
exit1:
StrCpy $R0 $R0 -$R1
exit2:
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

Function .onInit
ReadINIStr $R0 "$INSTDIR\operadef6.ini" "System" "Multi User"
StrCmp $R0 "" 0 +3
StrCpy $Yol "$APPDATA\Opera\Opera\Profile"
Goto End
Push $R0
Call GetFirstStrPart
Pop $R0
StrCmp $R0 1 0 End
StrCpy $Yol $APPDATA\Opera\Opera\Profile
Goto End
StrCpy $Yol $INSTDIR\Profile
End:
FunctionEnd

Sounds like GetFirstStrPart is doing an infinate loop (not sure why).
Anyway this code is cleaner:


Function .onInit
ClearErrors
ReadINIStr $R0 "$INSTDIR\operadef6.ini" "System" "Multi User"
IfErrors +2
StrCmp $R0 "" 0 +3
StrCpy $Yol "$APPDATA\Opera\Opera\Profile"
Goto End
Push $R0
Call GetFirstStrPart
Pop $R0
StrCmp $R0 1 0 +3
StrCpy $Yol $APPDATA\Opera\Opera\Profile
Goto End
StrCpy $Yol $INSTDIR\Profile
End:
FunctionEnd


-Stu

Thank you very much. All the codes work perfect now :)


Something similar
Hmm... i thought that i might add on here as well, what i'm trying to achieve...

Let me just put it straight, i make counter-strike source models, and have them compiled in zip format. What i've gotten tired of is always opening up directories and specifying locations, and also directing people all the time, so i came up with the idea to create a simple installer that can achieve these tasks.

First off, if i could, i'd use the classic interface, but i'm not sure if the classic interface supports these custom pages (never quite checked). I'm working on the Modern Interface at the moment.

e.g. my steam username is hamsteyr, and the files to be put in the game to replace existing models are kept in this directory, C:\Program Files\Valve\Steam\SteamApps\hamsteyr\counter-strike source\cstrike.

My problem now is that there are no registry keys which directly link to this, but there is one which links to C:\Program Files\Valve\Steam\.

What i've done is made it look for the registry, to get the C:\Program Files\Valve\Steam\, then add the \Steamapps\...\...

So what i've got now is "$INSTDIR\SteamApps\$STEAM_USER\counter-strike source\cstrike. The variable $STEAM_USER is what i'm trying to solve here. I've tried adding a custom page that asks for the input for the username, and then put it into the installer as the variable $STEAM_USER, but that doesn't work somehow. This is my example code so far.

InstallDir "CS:Source Not found, please specifiy location"
InstallDirRegKey HKLM "SOFTWARE\Valve\Steam" "InstallPath"
!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Docs\Modern UI\License.txt"
Page custom CustomPageA
;!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"

ReserveFile "Userpage.ini"

!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS

Var STEAM_USER

Function .onInit

!insertmacro MUI_INSTALLOPTIONS_EXTRACT "Userpage.ini"

FunctionEnd

Function CustomPageA

!insertmacro MUI_HEADER_TEXT "Steam username page" "Insert your Steam username in this page."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "Userpage.ini"

FunctionEnd

Section "" SecDummy

;Push $STEAM_USER

;!insertmacro MUI_INSTALLOPTIONS_READ $STEAM_USER "Userpage.ini" "Field 2" "State"

ReadINIStr $STEAM_USER "Userpage.ini" "Field 2" "State"

SetOutPath "$INSTDIR\SteamApps\$STEAM_USER\counter-strike source\cstrike"

File "c:\model.mdl"
SectionEnd


This is my Userpage.ini file
[Settings]
NumFields=2

[Field 1]
Type=label
Text=Your Steam username
Left=0
Right=-1
Top=0
Bottom=10

[Field 2]
Type=Text
Left=0
Right=-1
Top=20
Bottom=100
State=


Can anyone tell me why it wont work? Also, if the Directory page could show the full installdir, that would be awesome. O_o

http://nsis.sourceforge.net/Get_Stea...d_install_path

Searching the forum and Wiki usually helps :p

-Stu


I tried searching forums before i posted here, and since i've been cut back to dail up i kinda got fed up of looking O_o

Btw, is it me or is the page u gave me... umm... empty O_o


Originally posted by HaMsTeYr
Btw, is it me or is the page u gave me... umm... empty O_o
Someone vandalized the page a couple of hours ago. I've restored it.

Vandalised...? SWT... some people out there have no life at all =_= anyway, thanks for restoring it ;)

EDIT: I've read through the coding, and by the looks of it, the installer detects the steam user. What i'm trying to get at is for the user to specify the account name as one computer might not have just one steam user if u know what i mean. Any insight on how i could do this?