Custom Action not working msiexec /a - Visual Studio Setup Project - visual-studio

I have a visual studio setup project creating a setup.msi. I have some custom actions running during and after an installation.
When I execute the command msiexec.exe /a setup.msi /qn to upgrade an existing installation, the custom actions are not firing. It seems that the option /a (administrative execution) is bypassing the custom actions.
Any idea ?
Thank you in advance.

Administative installation runs in its own sequence inside the MSI. Hence you can actually insert custom actions there (though I would not recommend it), and they will run only during administrative installations.
You would need to insert these custom action in the normal installation sequence (as well) for them to ever run during normal installation (InstallExecuteSequence and / or InstallUISequence).
Normal Install:
InstallExecuteSequence
InstallUISequence
Administrative Install:
AdminExecuteSequence
AdminUISequence
Advertisement: There is also the advertisement sequence. This sequence uses the: AdvtUISequence and AdvtExecuteSequence tables. Advertisement is when you register the MSI package for installation later. Installation can be triggered by the user or via Add / Remove programs or via an application. Install-on-demand. Rarely used these days it seems (the main reason is probably the technical glitches and operational problems people face when trying to use it).
File Extraction: Administrative installation is essentially a glorified file extraction (equivalent to an unzip). It extracts all files, adjusts the media table to use external files and a few other things. It is basically intended to create an installation media to put on a networks share and also to allow the content of the MSI to be inspected. There is also the ability of MSI to "run feature from source" - which I have honestly never seen used successfully.
Note!: Though rather trivial, administrative installations are crucial for corporate packaging and the "transparency" of the MSI installation technology. This transparency is one of the key benefits of the MSI technology (list slightly down the page). Make sure that your MSI works properly during administrative installations. I think there is a bug in some WiX GUI-sets for example. There is a trick to make them work still by suppressing the GUI. Something like this: msiexec.exe /a MySetup.msi TARGETDIR=D:\ExtractHere /qn
What do you need the custom action to do during administrative installation?

Related

InstallShield Block installing same MSI twice from command line

I have setup created with InstallShield 2015 Basic MSI.
Let’s say in this setup user can choose if he want to install Client or Server,
for each setup type ( Client or Server ) there are several features he can choose to install.
Now user choose to install Client setup and included 2 features under it,
If he run the setup again with UI he will enter the maintenance mode enable him to add more feature belong to Client.
My problem is that he can also run same setup again from command line (msiexec /I) and try to install the Server setup type, currently setup doesn’t block or prevent it and this may cause corruption of Client setup he already have installed.
So, I guess I should write a CA that will check if current setup is installed and check what action user is trying to run from command line and if it’s not uninstall block it ( still need to support running uninstall from command line ).
Is this logic correct? How can I know what is the command user run from command line? meaning that he run msiexec /I and not trying to uninstall from command line.
I wonder if there an InstallShield\MSI build in way \ property to prevent installing same MSI twice from command line ?
I'm having a hard time understanding you. I hope my answer is aligned with your needs.
When you first run the MSI it's in installation mode. When you run it again it's a maintenance mode. Depending on how you authored your installer, you should get a dialog with Repair, Change or Remove buttons. The Change button can be used to allow the user to add additional features or remove features. This can all be done from the command line as well using the ADDLOCAL and REMOVE properties. There properties take a , delimited list of feature names.
One place people make a mistake is using the conditions Not Installed | REMOVE="ALL" on their custom actions. This doesn't take into consideration the fact that you might have multiple features and come back during maintenance mode and reconfigure the application. MSI has feature and component installation and action state evaluators that can be used in conditions that are better suited for this job.
Update:
I would write a Type 19 error custom action that blocks the installation if the user is requesting a two conflicting features to be installed or the user is requesting one feature to be installed that conflicts with another feature that is installed. Use the feature request and installed state operators in your conditional expressions and schedule it after CostFinalize.

MSI Silent Installation doesn't add registry and services entry

I have windows InstallShield Executable (.exe) without source files. This installer works in an interactive (GUI) manner. After installation, I can see the registry entry and entry in services.msc. Now there is a requirement to change it to silent installation for automation.
I have converted that InstallShield exe to msi using some extract options.
When I tried to install this MSI in silent manner using msiexec.exe, installation went fine but it was not adding those registry entry and services.msc entry,
This is the command I have used with admin user login via cmd prompt,
msiexec.exe /i app.msi /qn
Am I missing some thing here ?
NOTE - The problem here is I don't have the source for the InstallShield build just the executable alone.
I have seen additional properties like ALLUSERS and INSTALLLEVEL. Are there something else I need to add on this ?
I am trying this on Windows Server 2012 R2.
Sometimes an MSI performs custom actions after InstallFinalize in the InstallExecuteSequence. This is an error in design and can cause a silent install to fail since it never reaches these custom actions (installation ends at InstallFinalize). This is unlike an interactive run which will execute the custom actions after InstallFinalize before passing control back to the GUI sequence. It is also possible that custom actions are defined only in the GUI sequence causing them to never be run during a silent install - another error in design which isn't that uncommon.
Can you check with Orca or another tool whether there are custom actions after InstallFinalize in the InstallExecuteSequence? The bad news is that there is no good fix for this error, but you can try to run the installation by only showing a progress bar and see if this causes the custom action to be run:
msiexec.exe /i app.msi /qb-
This runs basic UI with no modal dialog boxes. Effectively a semi-silent setup. If this fails to try to run /qb instead of /qb-. The idea is to see if this executes the missing custom action by running with a minimal GUI so that the GUI sequence is run.
Finally, as Bogdan points out it is possible for the wrapper exe that you extracted the MSI from to contain additional installation logic that fails to run when you run the MSI alone.

Creating Basic MSI that invokes another msi installation

I have asked this exact question on the Flexara forum, but got no response up to today, so I want to ask it here.
We currently have a InstallScript project which runs fine. The resulting setup can be made unattended/silent fine.
In this setup we have some features and invoke a number of third-party installations (that are a prerequisite for running our software).
However, we have customers that want an MSI file and therefore we resorted to the Basic MSI project type.
The setup is made without too much hassle (I'm fairly new to InstallShield) and I can generate a .exe and .msi from this project.
However the only issue I have left is invoking one of the third-party installers.
That third-party installer (made with NSIS) on its turn invokes another installer which is MSI based.
This results in having error 1500 - the fact that you cannot run a msi type installation while another is running.
I've tried scheduling the CA (that are used to invoke the third-party installers) as the first action and as last, but no success.
Before resorting on the more unorthodox scenarios (like creating a task on Windows Task manager that runs after our installer finishes, or at the next reboot and forcing a reboot - which our customers don't like) or a scenario that we don't bundle the 'faulting' installer (we really like to be able to hand over a single intaller and not multiple), I'd thought I ask your input.
I've tried searching for solutions everywhere on the internet, but either I'm failing due to wrong keywords or I just didn't stumble on the right post yet.
Are there any options left for us to create a single MSI installer that is able to invoke this third-party installer (which invokes a msi installer on its turn)?
Since an EXE bootstrapper is not acceptable, there is only one solution:
store the prerequisite installers in Binary table of your MSI
create some custom actions which extract them from this table and launch them
schedule them in InstallUISequence, for example right before Progress dialog
use searches to detect if the prerequisites are installed or not
condition your custom actions with the search results
Basically, you need to launch them during the installation UI. It won't work if you launch them during InstallExecuteSequence.
I don't think the basic MSI project supports this, but it may be supported by more advanced project types. Other setup authoring tools offer direct support for this.
You can try InstallShield's "Chained .msi Package" feature.

How to use VS Installer class in a Custom Action

Dozens of Q&A entries (all but one in stackoverflow!) that I found got close to this question, but didn't teach me what I needed. I have what should be a nearly simple installation: a Windows service and an associated tray icon application. They install fine with the standard VS Setup project. After the files are installed, I need to present a dialog to the user to set some parameters in the service's exe.config file. In that dialog, the user should be able to abort the installation. I've tried two approaches to the Custom Action process and ran into a wall with each when it comes to making the installation roll back.
Approach 1: An exe for the Custom Action, run at Commit time.
This sort-of works. The application returns a non-zero exit code and the installation rollback occurs. What I don't like is that:
When the app exits (after the user selects to Cancel), the installation displays an error message saying that there was a problem with the installation and the user should contact the vendor. Since that's not the case, I'd prefer a more correct message ("Installation canceled by user") or no message at all.
Both of the project outputs (the service and the tray app) have to be listed under all four Custom Action sections or my dialog won't appear. Instead, an error appears about a missing InstallState file and the installation always fails. Intuitively, this seems wrong.
Approach 2: An Installer as the Custom Action, run at Install or Commit time.
This is cleaner to me (only the one item listed in the Custom Actions), but getting the process to roll back is worse than Approach 1. It seems that I have to throw an exception in the overridden method (Install/Commit), which then gives me several error dialogs before the rollback occurs, and then the rollback doesn't always uninstall the service.
What is the cleanest way to make this work without going to WiX or similar options?
The simple answer is don't use VS Installer Classes. They have a number of fundamental design flaws. I suggest you look at Windows Installer XML's ( WiX ) Deployment Tools Foundation ( DTF ) instead. DTF is a far superior hosting model / interop library for your managed code and outputs DLL's that are compatible ( from an MSI perspective ) with C/C++ custom actions. They can be consumed as Custom Actions by any MSI authoring tool, not just WiX installers.
Deployment Tools Foundation joins the WiX toolset.
Deployment Tools Foundation (DTF) Managed Custom Actions
I recommend this approach:
create a custom installation dialog which asks the user about your options
use the installer properties set by this dialog to modify your service configuration file (you can use a custom action or the XML support of another setup authoring tool)
This way the information is gathered before the install and the user can also abort the install without problems.
This approach is not supported by Visual Studio, but it can be done with free or commercial setup authoring tools.
If you want to stick with a custom action, you can try this:
make sure your custom action is deferred and doesn't run during commit (commit means that the installation was performed and there's no rollback)
use a Win32 DLL to show your custom dialog; this way you can return ERROR_INSTALL_USEREXIT (1602) so a friendlier user exit dialog is shown instead of the fatal error dialog

MSI Bootstrapping: External URLs

Much searching has lead me to find several descriptions of how to create a bootstrapping msi, but these solutions all assume the msi is local or a standard Windows component. Is there a way to make an msi that downloads an installer (which is also an msi) with normal MSI or Wix code rather than by having the bootstrapper execute some non-native program to do so?
My experience with msi's has been it's not possible to run 2 at the same time. (could be wrong though)
What I ended up doing was to instead make an installer exe using Inno Setup (http://www.jrsoftware.org) and ISTool (http://www.istool.org) which downloads and installs the various msi's. With ISTool it's very easy to do.
I know it's not as chic or sexy as Wix, but it worked for me very well.
I would create a custom action that runs in the InstallUISequence. This would download the MSI if necessary (to the source folder), and then try to launch it as a nested installation.
Windows prevents two installs from being in the InstallExecuteSequence at the same time, so if you're looking for a silent install solution with a bootstrapper, you're SOL.
However you can start another install from the UI sequence, which is probably an OK solution as long as you advise your customers that certain other dependencies must be installed first if they're going to deploy via group policy or some other 'silent' method.
If it helps, I'm pretty sure you can also call MSIEXEC with a URL, eg. msiexec.exe /i http://some.domain/blah.msi /passive
I would suggest that you write a native app and have it run the first msi and then run the seccons msi. I wrote a blog on how to do this. Here is a link (http://blog.foldertrack.com/?p=45)

Resources