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.
Related
I wanted to know how to call a function from C++ executable using NSIS.
I am using the below method but it is not calling the function.
!include LogicLib.nsh
Section
SetOutPath $INSTDIR
File E:\TestNullSoft\Test1.exe
File E:\TestNullSoft\Test2.dll
System::Call 'KERNEL32::AddDllDirectory(w "$INSTDIR")'
Pop $1 ;
${If} $0 = 0
MessageBox MB_OK "Function is NOT CALLED" IDOK
${EndIf}
SectionEnd
AddDllDirectory function is declared in the C++ project like as shown below:
You cannot call functions in .EXE files, only .DLL files.
Specifically, System::Call will call LoadLibrary and GetProcAddress and LoadLibrary cannot load a .EXE.
I'm currently using the following script to install drivers along with my application:
!macro customInstall
ExecWait '"$INSTDIR\resources\DPInst.exe" /sw'
!macroend
However, if DPInst returns >= 0x80010000, this means one or more of the driver installs has failed so I need to roll-back the installation and quit. Any idea how I would do this?
ExecWait can store the process exit code in the 2nd parameter. Not much you can do to roll it back, it is best just to do it early in the install phase:
!include LogicLib.nsh
Section
SetOutPath "$instdir\resources"
File "whatever\DPInst.exe"
ExecWait '"$INSTDIR\resources\DPInst.exe" /sw' $0
${If} $0 U>= 0x80010000
Delete "$INSTDIR\resources\DPInst.exe"
RMDir $instdir\resources
RMDir $instdir
MessageBox mb_iconstop "Error blah blah"
Abort
${EndIf}
SectionEnd
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 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
I'm using NSIS to create an installer which will install files from a web server. I'm using the NSISdl plugin to download the files but they are not downloading, it just says Download Failed: failed to open file.
This is the section which is doing the download, could I be missed something here.
Section "Aquiva"
; Set output path to the installation directory.
SetOutPath $INSTDIR
;Include files from this location, and copy that to the current
;out path
NSISdl::download http://41.78.239.158/Aquiva.exe
Pop $R0 ;Get the return value
StrCmp $R0 "success" +3
MessageBox MB_OK "Download failed: $R0"
Quit
SectionEnd ; end the section
You should use inetc for this purpose:
inetc::get "http://41.78.239.158/Aquiva.exe" "$EXEDIR\Aquiva.exe"
pop $R0
DetailPrint "Result: $R0"
You can get it here
If you insist on using NSISdl, your problem is probably due to not specifying the destination file, try this:
NSISdl::download http://41.78.239.158/Aquiva.exe "$INSTDIR\Aquiva.exe"
pop $R0
...