How to move a subdirectory with its contents to another directory with NSIS - nsis

this is the first time I work with NSIS, I want to edit an script NSIS to allow me:
If first instalation -> create the directory "Affaires" in the location "C:\Users\ali.ait-mouhoub.ext\AppData".
If it is an update (So the directory "Affaires" it already exists in "C:\N.O.E") -> move the directory "Affaires" with its contents to "C:\Users\ali.ait-mouhoub.ext\AppData".
The current script creates the directory "Affaires" in "C:\N.O.E".
Can you please help me modify my script to meet my needs?

If the both the new and old locations are on the same volume then you can use Rename:
Section
Rename "$InstDir\Stuff" "$InstDir\OldStuff"
SectionEnd
If the new location might be on a different volume then you have to copy+delete:
!include LogicLib.nsh
Section
ClearErrors
CopyFiles /Silent "$InstDir\Stuff" "x:\Backup"
${If} ${Errors}
MessageBox MB_ICONSTOP "Unable to move!"
${Else}
RMDir /R "$InstDir\Stuff"
${EndIf}
SectionEnd

Related

DLL Function is not calling from the NSIS installer when uninstalling

When uninstaling the software to do the complete cleanup calling the function in the C++ DLL .
To achieve this I am placing the DLL file in the temp directory. Then in the Uninstall section calling the DLL function. But it is not calling the function.
If I place that DLL file in the installed directory then it is calling the DLL function.
But I should not place it in the installed directory because I am calling this function when uninstalling.
Is it the correct way that I am doing? or is there any other way?
Below is my code snippet:
Section "MyApp"
InitPluginsDir
SetOutPath $PluginsDir
File "C:\Desktop\KillNofificationSoftly.dll"
SetOutPath $Temp
MessageBox MB_OK "Temp Path $Temp"
System::Call 'KERNEL32::AddDllDirectory(w "$PluginsDir")'
SetOutPath $INSTDIR
SectionEnd
Section "Uninstall"
System::Call "$PluginsDir\KillNofificationSoftly.dll::KillMeSoftly() i.r0 ?e"
Pop $1 ; LastError
${If} $0 = 0
MessageBox MB_OK "Success"
${EndIf}
SectionEnd
You are extracting the .DLL in the installer! $PluginsDir is deleted when the installer finishes. Move all the code to the uninstaller section.
If you are the author of this .DLL you should consider writing a NSIS plug-in, then it becomes just a single line of code, no need for System::Call.

How do I execute the app right after installation ... with arguments?

My installation EXE should unzip itself in a temp folder, then execute an app therein (with passing args), return and delete the temp folder again.
How do I write the nsi script?
It sounds to me like you are trying to create a portable application. Portable applications are always better when the original author adds support for it because it can handle registry and other configuration files correctly.
If you still want to create a launcher application you can do something like this:
OutFile "MyLauncher.exe"
RequestExecutionLevel User
SilentInstall Silent
SetCompressor LZMA
!include FileFunc.nsh
!insertmacro GetParameters
Section
${GetParameters} $1
InitPluginsDir
SetOutPath $PluginsDir
File "c:\myfiles\MyApp.exe"
File /r "c:\myfiles\otherfiles\*.*" ; If you need to include other files required by the application
ExecWait '"$PluginsDir\MyApp.exe" /param1 "pa ra m2" /param3 $1' $0 ; $1 contains the parameters passed to your launcher, remove it if you don't want to pass those arguments
SetErrorLevel $0
SetOutPath $Temp ; Don't lock $PluginsDir so it can be deleted automatically by the installer
SectionEnd
Answering my own question.
The required nsi script skeleton should look like this:
# The name of the installer (arbitrary)
Name "hello"
# The name of the installation file
OutFile "hello.exe"
# where put the installation - other options would be $TEMP, etc.
InstallDir $DESKTOP
RequestExecutionLevel user # no Windows UAC popup please!
SilentInstall silent # completely silent install
SetCompressor /SOLID /FINAL lzma # max compression for inst. file
# The stuff to install
Section ""
SetOutPath $INSTDIR # where to install (overwritable by user!)
File /r D:\...\... # where the install material lives
SectionEnd
# this function auto-runs after installation is fine
Function .onInstSuccess
# parameter are passed through via $CMDLINE
ExecWait '"$OUTDIR\hello.dist\hello.exe" $CMDLINE'
RMDir /r "$OUTDIR\hello.dist" # remove install folder again
FunctionEnd

Nsis temp folder

Function .onInit
DetailPrint "Temp folder - $TEMP"
System::Call 'Kernel32::GetTempFileName(t $TEMP, t "tmp", i 0, t.r0) i.r1
DetailPrint "Temp folder name - $0" //$0 gives empty string
FunctionEnd
When I call Kernel32::GetTempFileName in .onInit function i retrieves an empty file name. But when i call it from section everything is ok!
Can you explain me why?
I recommend you just call InitPluginsDir in .onInit and use $PLUGINSDIR as temp folder. It will be deleted automatically on exit.
$PLUGINSDIR
The path to a temporary folder created upon the first usage of a
plug-in or a call to InitPluginsDir. This folder is automatically
deleted when the installer exits.
It is important to quote all string parameters when using System::Call:
Section
System::Call 'Kernel32::GetTempFileName(t "$TEMP", t "tmp", i 0, t.r0) i.r1'
DetailPrint |$0|
SectionEnd
Please consider using $pluginsdir like the other answer suggests, it is a much better solution because it will not leave behind junk on the end-users machine...

Is it possible to conditionally add a file/folder to NSIS installer

Is it possible to conditionally add a file/folder and installation option to a NSIS installer?
My idea is that if the folder Foo exists at a given location it should be added to the installer and the option to install Foo should be added to the installer as well. But if the folder Foo does not exist, the NSIS script should just create the installer but leave Foo and the option to select Foo out of it.
You can try to include a file with /NONFATAL. If it exists, it will be included by the compiler. In runtime, you can check if installer was able to extract it.
File /NONFATAL "file.zip"
${If} ${FileExists} "$OUTDIR\file.zip"
...
${EndIf}
In NSIS 2 File /NONFATAL /R "c:\foo" is the best you can do without external tools and you need a little hack to hide the section when there are no files:
!include LogicLib.nsh
Page Components
Page InstFiles
Section "Main"
SetOutPath $InstDir
# File "C:\myfiles\myapp.exe"
SectionEnd
Section "Install Foo" SID_FOO
SetOutPath $InstDir
File /NONFATAL /r "C:\myfiles\foo\*.*"
SectionEnd
Function .onInit
SectionGetSize ${SID_FOO} $0
StrCmp $0 0 "" +3
SectionSetFlags ${SID_FOO} 0 ; Force all flags off including the checkmark
SectionSetText ${SID_FOO} "" ; Hide the section because its size is 0
FunctionEnd
If this is unacceptable you can use !system and get a little help from cmd.exe to check if something exists:
!tempfile INCEXIST
!system 'if exist "C:\myfiles\foo\*.*" echo !define HAVE_FOO > "${INCEXIST}"'
!include "${INCEXIST}"
!delfile "${INCEXIST}"
!ifdef HAVE_FOO
Section "Install Foo"
SetOutPath $InstDir
File /r "C:\myfiles\foo\*.*"
SectionEnd
!endif
In NSIS 3 !if supports a /FileExists switch:
!if /FileExists "C:\myfiles\foo\*.*"
Section "Install Foo"
SetOutPath $InstDir
File /r "C:\myfiles\foo\*.*"
SectionEnd
!endif
Example to replace file what depends on running service and exists or not at targget location
IfFileExists "$SYSDIR\my_file.dll" exist notexist
exist:
ExecWait 'net stop desired_service'
SetOutPath $SYSDIR
SetOverwrite on
File "/oname=$SYSDIR\my_file.dll" "Path to my file\my_file.dll"
ExecWait 'net start desired_service'
notexist:
.....what you want to do if doesn't exists

Not everything is deleted when I uninstall

I've made a simple installer that installs test.txt, but there are several problems:
The created folder+link in start menu isn't deleted
The uninstaller + folder isn't deleted
Does anyone know why?
#defines
outFile "Installer.exe"
installDir $DESKTOP\test
section
setOutPath $INSTDIR
writeUninstaller $INSTDIR\uninstaller.exe
createShortCut "$SMPROGRAMS\TestApplication\Uninstaller.lnk" "$INSTDIR\uninstaller.exe"
file test.txt
messageBox MB_OK "Hello World!"
sectionEnd
section "Uninstall"
delete $INSTDIR\uinstaller.exe
delete "$SMPROGRAMS\TestApplication\Uninstaller.lnk"
delete $INSTDIR\test.txt
sectionEnd
http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista
and use RmDir "$INSTDIR" after the delete commands to delete the install folder
In addition to the answers pointing out that you never call RmDir $INSTDIR, you've also mistyped the uninstaller executable name:
delete $INSTDIR\uinstaller.exe
You've missed the 'n'.

Resources