NSIS Installer Run Batch File - nsis

Trying to run a batch file at the end of an installation, everything works great except this file won't run.
section "Startup"
Exec '"$0" /C "C:\Program Files\placeholder\startup\startup.bat"'
sectionEnd
Everything gets deposited in the right spot, using absolute pathing to call this. I asked for administrator privileges at the start,
RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on)
Just copying from the example NSIS installer provided here
The file is there so I must be making a mistake with the file path or missing some parameter. Been trying a lot of permutations like nsExec but not sure my mistake. Hopefully this is a simple mistake and will aid others in the same boat at some time.

Without more information I would guess that this is a 64-bit Windows machine and filesystem redirection is causing your 32-bit installer to access the wrong program files directory.
The code you posted is also problematic because we don't know what $0 is. I assume you failed to post the code where it expands %comspec%. To rule out this, replace $0 with $sysdir\cmd.exe.
Ideally your installer should extract the batch file to the destination directory:
Section
SetOutPath $InstDir
File batch.bat
ExecWait '"$sysdir\cmd.exe" /C if 1==1 "$InstDir\batch.bat"'
SectionEnd
If you must access the 64-bit folder you can disable the redirection but this is not recommended:
!include x64.nsh
Section
${DisableX64FSRedirection}
ExecWait ... $ProgramFiles64\...
${EnableX64FSRedirection}
SectionEnd

I think that you should give us more information to solve this problem.
Based on current information, I guess there are two reasons:
"C:\Program Files" is a path for 64-bit programs, but NSIS installer is a 32-bit program, so this path will be redirected to "C:\Program Files (x86)". You can use the solution from Anders to solve it.
Your batch file may contains relative paths. When you run your batch file from the NSIS installer, your working directory is not as same as your batch file. Due to this, some command cannot run correctly. You can use %~dp0 to solve it.

Related

specificing destination directory in nsis (zipped installation)

I'm new to NSIS and creating one installer for our project.
The requirement is: there are 1 folder and 2 exes needs to be installed as part installation. These exes are created using nsis (Y.exe, Z.exe). These exes should be installed in different destination folder. I've tried this two approches:
Approach 1:
in script these variables assigned
RUN_Y C:\Installer\misc_exe\y.exe
RUN_Z C:\Installer\misc_exe\y.exe
Y_INSTALL_DIR INSTDIR\Y\ # INSTDIR is specified by user during folder installation
Z_INSTALL_DIR INSTDIR\Z\ # INSTDIR is specified by user during folder installation
# calling this at the time exe installation
setoutpath SetOutpath "${Y_INSTALL_DIR}"
ExecWait '"${RUN_Y}"'
setoutpath SetOutpath "${Z_INSTALL_DIR}"
ExecWait '"${RUN_Z}"'
Problem is, the destination folder is always coming as C:\Installer\misc_exe\ , whereas it should be C:\Y\. How can I fix it?
Approach 2:
While creating the zipped folder to exe, I gave destination folder as $INSTDIR/Y/ and $INSTDIR/Z/, and I think, this $INSTDIR is taken from the 1st folder installation. But, its not working that way.
can anyone help with me with how can I do specific folder installation?
Thanks in advance.
I am not sure what are you trying to do but to set target directory use
InstallDir "C:\Y\"
command.

Extended NSIS plugins directory

I am building a plugin for NSIS with VS 2010 and I would love to set up the project so that a test setup is automatically built from a simple NSI file.
All seems fine except I can't figure out how to make NSIS look for my plugin in my project's output folder instead of C:\Program Files (x86)\NSIS\Plugins\*.dll only.
Are there any commands I can put in my NSI script to make NSIS look for my freshly built plugin outside of "standard plugins folder"? It seems rather odd to have to copy my DLL each time I wanted to test it.
Any help is appreciated.
You can use !addplugindir directive, see nsis compile-time commands.
Use !addplugindir directive with defined symbol (/D on command line).
Symbol is "the path to your location of .dll file"
For VS 2010 is the best option to use Visual & Installer - free VS addin for developing NSIS installers directly in Visual Studio.
Set your symbol in Project properties:
Download here: www.unsigned-softworks.sk/visual-installer/
As others have mentioned, the !addplugindir directive in your NSI script file will do the trick, and you can define a variable to pass to that directive on the command line using /D.
As for the code to add to your NSI file, you need something like this:
!ifdef EXTRANSISPLUGINSFOLDER
!addplugindir "${EXTRANSISPLUGINSFOLDER}"
!endif
Then on the command line, you can call your NSI script like this:
makensis.exe /DEXTRANSISPLUGINSFOLDER=C:\somefolder\moreplugins\ YourInstallerScript.nsi
When defining the extra folder, you might find that having any spaces in the folder path causes problems, and using quotes around the path doesn't help. To work around this, try using the dir /x command in the Windows terminal to list the 8.3 DOS names for the folders with spaces in their name. This will help you build up a folder path that doesn't contain spaces. (eg C:\Program Files\ often becomes C:\PROGRA~1 when listed with dir /x from the root of C:)
May have missed the point here but could you not have used an XCOPY post build event to copy the output to the NSIS plugins directory?

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.

Execute files which are generated while runtime

Still in progress with NSIS Setup.
The thing is now I´m executing NSIS executables during my "main" setup. Those other setups, which I´m executing, generate uninstaller for themselve. When I´m performing the uninstaller in the main setup I would like to call those generated uninstaller files.
I´m doing the execution with nsExec::ExecToLog but if a executable is not from the decompressed from the .exe you won´t be able to execute it. Am I right? Is there any solution to solve this problem?
I´m very grateful for every answer!
You can use nsExec::ExecToLog with whatever you like.
It could be extracted:
SetOutPath $INSTDIR
File foo.exe
nsExec::ExecToLog $INSTDIR\foo.exe
It could be a path already known:
nsExec::ExecToLog $WINDIR\bar.exe
It could be calculated:
ReadINIStr $0 $INSTDIR\uninstaller-paths.ini UninstallerPaths baz
nsExec::ExecToLog $0
It really doesn't matter. As far as the script is concerned, it's purely a command string to execute.

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