NSIS ExecWait not launching secondary installer - nsis

I have a basic NSIS installer that is supposed to call a secondary - non-NSIS installer like so:
Section "Install First" SEC01
File "WindowsPathToFile\setup.exe"
DetailPrint "Installing the first Thing"
ExecWait '"$INSTDIR\setup.exe"'
SectionEnd
NSIS and the installer do not throw any errors - however the sub installer is never launched or executed (and the application is never installed).
Note that if I put the call to "setup.exe" in a batch script and launch the batch script this does work. I was just hoping for something more elegant (that doesn't display the command prompt) as I'll have several custom installers that need to be called.
I didn't think that the ExecWait chain issue detailed in "ExecWait Doesn't Wait" would affect me as I don't think my (setup.exe) installer is extracting a secondary installer.
The setup.exe installer is created by LabVIEW and I haven't found good information on what it's doing behind the scenes.
Am I missing something here? Or do I just need to stick with the batch script?

Does the secondary installer require elevation? Do you have RequestExecutionLevel admin in your .nsi?
ExecWait internally calls the CreateProcess Windows API function and it will fail if the child process needs to be elevated by UAC.
If you are going to execute a child process that requires elevation then it is generally recommended that your installer requires elevation as well. If you for some reason don't want to do this then you can use ShellExecWait or ${StdUtils.ExecShellWaitEx}.

Related

Inno Setup: Calling uninstaller while in setup - is that a proper way to rollback?

I've got a task to sort out a problem with our product installer and eventually came to a dead end with no ideas.
The installation process goes like:
Install files
Configure some services in [Run] section
Run our custom product configurator
If step 3 is successful (configurator returned good exit code) then start those services
else rollback installation
So the issue was something Shroedinger's - on SOME machines there were unexpected reboot after cancelling install in configurator, without any questions. Of course that annoyed users.
I couldn't figure out the criteria by which the machine decided to reboot, but I stumbled onto this thing:
In [Run] section
Filename: "stub.exe"; Flags: runhidden skipifdoesntexist; BeforeInstall: ConfigureService
Then in [Code], ConfigureService calls for InstallationAbort proc if configurator returned bad exit code.
Next, in InstallationAbort:
Exec(ExpandConstant('{uninstallexe}'), '/VERYSILENT /noinstancecheck', '', SW_HIDE,
ewWaitUntilTerminated, ErrorCode);
So the author calls for uninstaller WHILE IN THE INSTALLER.
Using logs I determined, that installation program doesn't end after uninstaller completes work! It's moving to the next step (installation finished)! After that I can see in log
Restart needed? Yes
Note: system never reboots if configurator is not cancelled, i.e installation finishes the right way.
So what I tried:
Adding /NORESTART to uninstaller Exec call. Doesn't help. I think that's because it's installer, who decides to make a restart.
Adding WizardForm.CancelButton.OnClick(WizardForm.CancelButton); and some other calls to exit setup after call to uninstaller. Doesn't help.
Overriding NeedRestart function to return false in case of cancellation
As I tried to understand, author calls uninstaller because of need to delete installed services (i.e. call them in UninstallRun with special parameters)
So, my main question: Is that a normal practice to call uninstaller from code called from [Run] section, to undo changes made in [Run]?
Is that a normal practice to call uninstaller from code called from [Run] section, to undo changes made in [Run]?
In general, it's not a common practice. One should not abort installation in Run section. Inno Setup is not designed to handle that.
But if you need to, there's no other way. The code you have is most probably based on this:
How to force Inno Setup setup to fail when Run command fails?
But that does not imply that the installer should require reboot. There's some conflict between the installer and uninstaller.

Rights elevation with UAC

I've just developed a .NET program which has the ability to patch itself.
I've noticed that the patching process only runs if I choose "run as administrator".
It seems I need to "create and embedd an Application Manifest", according this this:
https://msdn.microsoft.com/en-us/library/bb756929.aspx
So my question:
Is it normal for applications like mine (which can patch themselves) to require Admin rights, and is this the route I should be going?
Thanks
If your application does not normally require elevation then I don't recommend that you request it in your manifest because it will be very annoying for your users. Firefox uses a NT service to get around the UAC dialog but I can't really recommend that either unless your updates are very frequent.
I would suggest that you write a little updater application that does the patching. It can request elevation in its manifest and this way the user only has to elevate when there is something to patch. If you don't want another .exe in your bundle, you can execute yourself again with the runas verb when you need to patch.
Edited the NSIS script to include this line:
AccessControl::GrantOnFile \"$INSTDIR" "(S-1-5-32-545)" "FullAccess"
This gave the User account full access to the application folder within Program Files, meaning my patcher could write to it without any problems.

In Inno Setup, how to rollback a "verysilent" installation?

I have created an installer using Inno Setup. The installer uses a packaged-in DLL to check availability of a specific device on the target machine. If the device is found, the installation is allowed to finish, otherwise the installation is rolled-back (rollback is done using below lines in script):
if <DeviceNotFound> then
begin
CancelWithoutPrompt := true;
WizardForm.Close;
end;
I have checked that the above check and rollback logic works fine if the setup is run with /silent cmd line param. However, when I use /silent param, the setup displays the Installation progress wizard form.
Also, I found that if I run the above setup in /verysilent mode, then the "DeviceNotFound" check logic works fine but the rollback logic doesn't work and it seems as if rollback logic doesn't get executed at all. Instead of performing rollback, the installer successfully installs.
Now, I have a requirement to run the setup silently so that no window is displayed but it must install or rollback based on device check. Therefore, I have the below queries:
Can I rollback the installer when it is running in /verysilent mode? If so, please advise how it may be achieved. I can detect verysilent install mode as shown in question:
How to detect whether the setup runs in very silent mode?
Alternatively, can I Hide/Minimize the Installation progress window when it is running in /silent mode? If so, please advise how it may be achieved.
Please help me with my above queries.
Sorry to be so descriptive but I tried to explain my problem and queries!
EDIT
I am not doing the above mentioned check in InitializeSetup(). I am doing the check from a function invoked by AfterInstall directive from [Files] section. I have a limitation that I cannot do it from InitializeSetup() as the packaged-in DLL is not extracted till [Files] section completes. I also need to run the installer in Windows PE (Preinstallation Environment), hence I cannot use ExtractTemporaryFile() function to forcefully extract the DLL because the {tmp} path is not valid in that environment. That leaves me with only one option is to check after [Files] section is done. Please advise!
Your constraint on not using ExtractTemporaryFile does not make sense.
The Inno Setup installer always creates a temporary folder for the installation.
2015-07-31 09:02:07.458 Created temporary directory: C:\Users\martin\AppData\Local\Temp\is-1CN29.tmp
If it is not possible to create the folder, the installation fails.
The Inno Setup tries to create the temporary folder in these locations:
%TMP%
%TEMP%
%USERPROFILE%
Windows installation folder (C:\Windows)
At least the last path has to exist even in the "Windows PE".
So I do not think, there's anything preventing you from using the ExtractTemporaryFile function.

How to run something just before the files are installed?

I would like to know how to run something just before files are installed using NSIS.
I know about the .onInit function. That function runs when the installer is first starting. That is not what I want. I would like to run something after the user has clicked the install button but before the files actually get installed.
To be more specific. I have a windows service. When the installer is upgrading the windows service, I need it to stop the service - but only once the user is committed to the install - not when first starting the installer. Then it can upgrade the files and finally (re)start the service again. This seems like it should be a common requirement, but I haven't been able to find anything.
If it matters I'm using the MUI instead of classic.
All sections are executed on the instfiles page and they are executed in the same order as your source .nsi so you can just add another (hidden) section:
Section
# Do service stuff...
SectionEnd
Section "Required Files"
File xyz.abc
SectionEnd
Section
# Do service stuff...
SectionEnd
As Anders said - create invisible (hidden) section which is very first of all sections in your script and stop the service there.
When the other sections will be executed the service will be stopped.
Tip: maybe you should wait few seconds to let service manager time to stop the service.

INNO: Disallow "Ignore" when file is in use

I am using Inno Setup for the installer for my windows application. If a user has the application when the installer is run (eg. for an update), the installer will stop when it is unable to replace a file in use, and it allows the user to select whether to Abort, Ignore, or Retry.
I would like it to only allow Abort or Retry and remove the option to Ignore. Does anyone know how this can be done?
Or if this can't be done, how can I make the installer abort if the application is running?
The easy way to detect whether the application is running requires co-operation from the application, so it's best to work this out before you ship your first version. Use Inno Setup's AppMutex setting. There is an example in the Inno Setup knowledge base for setting up a mutex visible in multiple sessions. There is more about AppMutex in Inno Setup's help file.

Resources