NSIS weird behavior with GetParameters - windows

I'm having a weird error with NSIS:
!include "MUI2.nsh"
!include "FileFunc.nsh" # To use GetParameters
Name nsDialogs
OutFile nsDialogs.exe
Function .onInit
${GetParameters} $R0
MessageBox MB_OK "$R0"
FunctionEnd
!insertmacro MUI_PAGE_WELCOME
Section
DetailPrint "hello world"
SectionEnd
If I use this command line
nsDialogs.exe /d=hello
the message box says: "/d=hello" as expected, but if I use
nsDialogs.exe /D=hello
the message box says "" and this is wrong.
Why is this happening?

From the documentation:
/D sets the default installation directory ($INSTDIR), overriding
InstallDir and InstallDirRegKey. It must be the last parameter used in
the command line and must not contain any quotes, even if the path
contains spaces. Only absolute paths are supported.
This means you cannot use /D with ${GetParameters} (/S and /NCRC are also switches used by NSIS). NSIS by design uses everything after /D= as $instdir.
The only way to detect /D is to not use InstallDir[RegKey] in your script and check if $instdir is != "" in .onInit

/D is command line parameter that let define the installation directory directly from the installer command line invocation.
See the Installer usage / Common Options chapter for details.

I don't know for sure, but I assume that NSIS strips out its inbuilt parameters by default. In that case you could try something like this:
!define myInstDir "$PROGRAMFILES\myApp"
Function .onInit
${GetParameters} $R0
StrCpy $R0 ${myInstDir} +2
MessageBox MB_OK "$$INSTDIR was changed on runtime"
FunctionEnd

Related

NSIS GetParent functon throws an unknown error

In my NSIS installer script I am trying to use the GetParent macro defined in FileFunc.nsh but I get a strange error. Anybody a clue why?
Here is my script code
!include "FileFunc.nsh"
Section
${GetParent} "$INSTDIR" $parentDir
SectionEnd
And the error I get is:
!insertmacro: GetParentCall
Usage: Pop $(user_var: output)
Error in macro GetParentCall on macroline 5
I am using NSIS 2.46
The $parentDir variable has not been declared, try:
!include "FileFunc.nsh"
Var parentDir
Section
${GetParent} "$INSTDIR" $parentDir
SectionEnd
Only $0..$9, $R0..$R9 and a handful of other ($instdir etc.) documented variables exist by default.

How to bundle exe file inside another exe file using nsis script

I have a installer file called sample.exe. This exe file will have some components that use have to be defined such as port number, installation directory and etc. I have to bundle this sample.exe file inside another installer called test.exe. So when i try to install the test.exe, it should also install the sample.exe. i could see there are options to achieve this in nsis, but how to provide options for the use to enter the port, directory path of sample.exe while installing the test.exe ? i am beginner to nsis and any reference are example script will help me lot. Thanks in advance.
You need to create custom (installer) page where these values are entered.
Use nsDialogs for this (recommended): http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html
There is no exact solution for this as your specification is really vague, rather check the examples and use provided code snippets from them.
You generally use the directory page to let the user choose the installation directory. Non-standard user input can be recorded on a custom page using the nsDialogs plug-in:
Name "Foo"
OutFile "TestSetup.exe"
RequestExecutionLevel admin
InstallDir "$ProgramFiles\Test"
!define DEFAULTPORT 666
!include nsDialogs.nsh
Var MyPort
Var PortEdit
Function .onInit
StrCpy $MyPort "${DEFAULTPORT}"
FunctionEnd
Page Directory
Page Custom MyPageCreate MyPageLeave
Page InstFiles
Function MyPageCreate
nsDialogs::Create 1018
Pop $0
${NSD_CreateLabel} 0u 10% 20u 12u "Port: "
Pop $0
${NSD_CreateNumber} 20u 10% 40u 12u "$MyPort"
Pop $PortEdit
nsDialogs::Show
FunctionEnd
Function MyPageLeave
${NSD_GetText} $PortEdit $MyPort
FunctionEnd
Section
SetOutPath $InstDir
File "Sample.exe"
; Write the chosen port to a config file:
WriteIniStr "$InstDir\Config.ini" "Network" "Port" "$MyPort"
SectionEnd

overwrite files created by emmbeded installer

So I embedded two installers into my install script created with nsis, the whole thing is supposed to install one program then the other one, and then overwrite three files created by the second installer with newer versions. The problem is that those three files get created before the second installer gets to work. How can I make sure that these files get created only after the second installer finish it's job?
`
!include "MUI2.nsh"
; The name of the installer
Name "ADIS"
RequestExecutionLevel user
; The file to write
OutFile "ADIS.exe"
Unicode true
; The default installation directory
InstallDir "C:\ADIS"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Spanish"
;--------------------------------
; The stuff to install
Section ""
; Set output path to the installation directory.
SetOutPath $INSTDIR
RMDir /r $INSTDIR
SectionEnd
SectionGroup "instaladores"
Section "Firebird"
ExecWait "Firebird\Firebird-2.5.4.26856_0_Win32.exe"
SectionEnd
Section "Cliente"a
ExecWait "Cliente\setup.exe"
SectionEnd
SectionGroupEnd
Section "Actualiza"
; Put file there
;File Nvo\ADIS.exe
;File Nvo\ADIS.ICO
;File Nvo\ADIS.GDB
File /r "Nvo\*"
SectionEnd`
You should probably run "Cliente\setup.exe" silently. Most installers have a silent switch you can use on the command line and some also provide a wait switch so you can wait even if the installer uses child processes.
What happens if you add a MessageBox before the file command and don't click it until the other installers have completed?

NSIS, detect if directory exists during installation

I have installer, which supports choosing installation directory. And I want to detect if given folder exists and if it is empty. If it is NOT empty, show warning message box, then remove all its contents and install program into that folder. Only problem is to get into the right code section, where I can get installation folder given by user during installation, I can handle the rest.
Thank you for any advices.
Normally you would just check if the directory exists:
Outfile "$%Temp%\Test.exe"
RequestExecutionLevel user
InstallDir "$Documents\Test"
!include LogicLib.nsh
Page Directory "" "" DirLeave
Page InstFiles
Function DirLeave
${If} ${FileExists} "$InstDir\*"
MessageBox MB_YESNO `"$InstDir" already exists, delete it's content and continue installing?` IDYES yep
Abort
yep:
RMDir /r "$InstDir"
${EndIf}
FunctionEnd
Section
SetOutPath $InstDir
File myfile.ext
SectionEnd
This will also display the message if the directory exists but is empty. To work around that you would need some custom detection:
!macro _IsNonEmptyDirectory _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!insertmacro _IncreaseCounter
Push $0
FindFirst $0 $_LOGICLIB_TEMP "${_b}\*"
_IsNonEmptyDirectory_loop${LOGICLIB_COUNTER}:
StrCmp "" $_LOGICLIB_TEMP _IsNonEmptyDirectory_done${LOGICLIB_COUNTER}
StrCmp "." $_LOGICLIB_TEMP +2
StrCmp ".." $_LOGICLIB_TEMP 0 _IsNonEmptyDirectory_done${LOGICLIB_COUNTER}
FindNext $0 $_LOGICLIB_TEMP
Goto _IsNonEmptyDirectory_loop${LOGICLIB_COUNTER}
_IsNonEmptyDirectory_done${LOGICLIB_COUNTER}:
FindClose $0
Pop $0
!insertmacro _!= "" $_LOGICLIB_TEMP `${_t}` `${_f}`
!macroend
!define IsNonEmptyDirectory `"" IsNonEmptyDirectory`
Function DirLeave
${If} ${IsNonEmptyDirectory} "$InstDir"
MessageBox MB_YESNO `"$InstDir" already exists, delete it's content and continue installing?` IDYES yep
Abort
yep:
RMDir /r "$InstDir"
${EndIf}
FunctionEnd

Writting Folder causes error code 80

My NSIS installer is giving a error code of 80 when I attempt to copy/overwrite a folder. I think it may have to do with the fact that the folder I am attempting to copy to the users HD already exists. But in my case I will always want to overwrite it.
What does the error code 80 mean?
Heres my code:
# Write plugins to EXDS_Customisation\EXDS_USER\
ClearErrors
SetOverwrite try
SetOutPath "$INSTDIR\EXDS_User\"
FILE /r "${localInstallDir}\EXDS_Customisation\EXDS_User\${MAINPLUGINSDIR}"
${If} ${Errors}
System::Call "Kernel32::GetLastError() i() .r1"
# Prints: "Error code: 80"
MessageBox MB_ICONINFORMATION|MB_OK "Error code: $1 "
Quit
${EndIf}
If you always want to overwrite, why are you using Try and not SetOverwrite On?
Using System::Call "Kernel32::GetLastError()... is never valid. System::Call has a special ?e option but it is not useful in your case. You cannot get specific error information from NSIS, all you have is just the error flag...

Resources