NSIS Identifying multiple uninstallers - nsis

I have multiple instances of a program and each has its own install directory with its own copy of the uninstaller. The installer has a field called "$instance" entered by the user which is recorded in the registry like this:
HKLM "SOFTWARE\#vendor.name#\#product.name# #product.version#\installs\$instance"
which works fine. This key contains the root path of the install.
I would like to uninstall the instance of the program that corresponds to the uninstaller that is executed but the Uninstall section does not retain the variable "$instance" that the user entered at install time.
Any ideas?
Example:
Section Uninstall
; THIS does not display the instance name. :(
MessageBox MB_OK "$instance"
SectionEnd

You can store custom data at the end of the uninstaller.exe without breaking the CRC check, or alternatively store it in a .ini in the same directory as the uninstaller (I do this all the time, just name the ini file "uninstaller.dat" or something like that so users don't mess with it)

Related

NSIS: Writing to registry (not HKLM)

Please help me: I want to write some data to registry. You might say "Wait, wait, this is one of the basic features in NSIS!", but, I want to write to the app registry (HKCU, not HKLM). The main purpose is: when the installer installs my product it also installs my update manager. I just want to write the product installation directory to the Updater branch, so it can further fetch the update package and install it to the product directory.
If you have RequestExecutionLevel admin in your script and you are installing to $ProgramFiles then you are doing a machine/all users install and the installer should not write to HKCU. Your application must initialize its entries in HKCU and AppData the first time the user runs it. You cannot do it in the installer because UAC might run the installer as the "wrong" user.
If you have RequestExecutionLevel user in your script then you are doing a single user install and the installer should only write to HKCU and [Local]AppData.

using NISIS uninstaller to create an uninstaller

I am getting an error when I am trying to uninstall an application. I used NSIS to make installer and uninstaller for it. The application is uninstalled but it is not getting removed from the add/remove programs. the error looks like "an error occurred while trying to uninstall it may have already been uninstalled"
You need to delete the registry key relation to the Add/Remove Programs registration in your uninstall section.
See also the last paragraph of section "Required values" here.
For example, it could look like this:
Section Uninstall
; ...here the existing uninstall code goes...
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\WhateverNameYouHadUsedHereBefore"
SectionEnd

Why my uninstaller is not working properly in nsis?

I have written a nsis script in which i need to prompt the user where there was previous installation and uninstall the previous version if user select the same folder as previous version.It is working fine.But suppose user choose different directory than the uninstall.exe is giving problem.
Ex-suppose user install version 1.2 in folder a and then agian version 1.2 in folder B .
Than in every case the uninstall .exe is pointing to folderb not folder a.How can i solve this issue
In the uninstaller, $instdir is just the directory the uninstaller is in so the uninstaller itself should not care.
You say you are prompting the user, so you already know the location of the old install so all you have to do is to invoke the uninstaller with the special parameter so it knows where to uninstall from...

My NSIS script's Uninstall isn't deleting links from ProgramData directory

Got another newbie NSIS question. Here's the script:
; -*-nsis-*-
Name "ndhtest"
OutFile "FooStartMenuTest.exe"
XPStyle on
!define FOO_SRC c:\users\nhughes\foo
InstallDir "$PROGRAMFILES\Initech\"
Icon ${FOO_SRC}\foo_logo.ico
UninstallIcon ${FOO_SRC}\uninstall.ico
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
Section
SetOutPath $INSTDIR
File ${FOO_SRC}\foo.bat
WriteUninstaller "$INSTDIR\uninstall.exe"
CreateDirectory $SMPROGRAMS\Initech
CreateShortCut $SMPROGRAMS\Initech\Foo.lnk $INSTDIR\foo.bat "" \
"${FOO_SRC}\foo_logo.ico"
CreateShortCut $SMPROGRAMS\Initech\Uninstall.lnk $INSTDIR\uninstall.exe "" \
"${FOO_SRC}\uninstall.ico"
SectionEnd
Section "Uninstall"
Delete $SMPROGRAMS\Initech\Foo.lnk
Delete $SMPROGRAMS\Initech\Uninstall.lnk
RMDir $SMPROGRAMS\Initech
Delete $INSTDIR\Foo.bat
Delete $INSTDIR\uninstall.exe
RMDir $INSTDIR
SectionEnd
The uninstall seems to work except for leaving the shortcuts under ProgramData:
Directory of c:\ProgramData\Microsoft\Windows\Start Menu\Programs\Initech
08/10/2011 04:07 PM <DIR> .
08/10/2011 04:07 PM <DIR> ..
08/10/2011 04:23 PM 1,847 Foo.lnk
08/10/2011 04:23 PM 1,885 Uninstall.lnk
2 File(s) 3,732 bytes
2 Dir(s) 1,387,345,117,184 bytes free
What is my script getting wrong that is leaving this stuff hanging around?
Here is what the uninstaller writes to its console (I added a DetailPrint message listing $SMPROGRAMS):
smprograms=C:\Users\nhughes\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Remove folder: C:\Users\nhughes\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Initech\
Delete file: C:\Program Files (x86)\Initech\foo.bat
Delete file: C:\Program Files (x86)\Initech\uninstall.exe
Remove folder: C:\Program Files (x86)\Initech\
Completed
So the links under ProgramData never get referred to, it's looking for the links under AppData\Roaming instead.
I'm testing this on Windows 7, but the core problem here is I would like to be able to write a script that works on everything from XP to Windows 7, regardless of all the changes in how Windows squirrels away stuff in different spots in different versions. This is looking like it might be painful.
If DetailPrint is added to the nsis script, it starts to be apparent that NSIS tries to create the files under C:\Users, but they are actually created in c:\ProgramData. This ProgramData directory is a strange thing, because it's not visible with dir C:\, however it's possible to enter the directory with cd. Such mysteries are caused by Virtual Store, a tricky feature of Windows 7.
Now to the solution. Windows applications should define their execution level, otherwise system may behave in an unexpected way. You remember some applications ask whether to install "for current user only" or "for all users"? That's the thing we need to declare.
If we insert nsis instruction RequestExecutionLevel user, then the shortcuts are made for current user. If we do RequestExecutionLevel admin, then we should also add SetShellVarContext all to both install and uninstall sections.
This answer is based on the article from nsis wiki: Shortcuts removal fails on Windows Vista, where examples are given for both approaches.
From the spec:
4.9.1.8 RMDir
[/r] [/REBOOTOK] directory_name
Remove the specified directory (fully qualified path with no wildcards). Without /r, the directory will only be removed if it is completely empty. If /r is specified, the directory will be removed recursively, so all directories and files in the specified directory will be removed. If /REBOOTOK is specified, any file or directory which could not have been removed during the process will be removed on reboot -- if any file or directory will be removed on a reboot, the reboot flag will be set. The error flag is set if any file or directory cannot be removed.
Try adding the /r to the RMDir lines to force it to flush the contents. Either that or remove the links individually.

Is it possible to package an exe into an NSIS generated installer which runs first?

Is it possible to generate an NSIS installer (using a .nsi) which packages an exe (let's say foobar.exe) which is then run before the installer actually installs the program as normal? I assume it'd have to extract the exe to a temp dir before running it, which is fine. It must be run before the main install however.
Initpluginsdir
File "/oname=$pluginsdir\myapp.exe" "c:\build\myapp.exe"
ExecWait '"$pluginsdir\myapp.exe"'
Delete "$pluginsdir\myapp.exe" ;delete is optional, $pluginsdir is auto-deleted when installer quits
Put before other code in your first section or in .onInit (Depending on what myapp.exe does etc)

Resources